商城首页欢迎来到中国正版软件门户

您的位置: 首页 > 文章列表 > 编程开发 > java %0d,我如何使java.text.NumberFormat格式0.0d为“0”而不是“+0”?

java %0d,我如何使java.text.NumberFormat格式0.0d为“0”而不是“+0”?

  发布于2026-07-16 阅读(0)

扫一扫,手机访问

在Ja va的数值格式化中,有时会遇到一个看似简单却很棘手的需求:既要显示正负号,又希望零值不带符号,直接显示为“0”。比如:-123.45 → “-123.45”,123.45 → “+123.45”,而0.0则要输出为“0”。

如果直接用DecimalFormatsetPositivePrefix("+"),你会发现0也会被格式化为“+0”——这显然不是我们想要的。那么,如何优雅地解决这个问题?

解决方案

这里可以借助ChoiceFormat来动态选择前缀。思路是:当数值为0时,不加任何前缀;当数值大于0时,加上“+”;负数则沿用默认的“-”。下面是一个完整的实现示例:

import static org.junit.Assert.assertEquals;
import ja va.text.ChoiceFormat;
import ja va.text.DecimalFormat;
import ja va.text.FieldPosition;
import ja va.text.NumberFormat;
import ja va.text.ParsePosition;
import org.junit.Test;

public class NumberFormatTest {
    @Test
    public void testNumberFormat() {
        NumberFormat nf = new MyNumberFormat();
        assertEquals("-1234.4", nf.format(-1234.4));
        assertEquals("0.0", nf.format(0));
        assertEquals("+0.3", nf.format(0.3));
        assertEquals("+12.0", nf.format(12));
    }
}

class MyNumberFormat extends NumberFormat {
    private DecimalFormat df = new DecimalFormat("0.0#");
    private ChoiceFormat cf = new ChoiceFormat(
        new double[] { 0.0, ChoiceFormat.nextDouble(0.0) },
        new String[] { "", "+" });

    @Override
    public StringBuffer format(double number, StringBuffer toAppendTo,
            FieldPosition pos) {
        return toAppendTo.append(cf.format(number)).append(df.format(number));
    }

    @Override
    public StringBuffer format(long number, StringBuffer toAppendTo,
            FieldPosition pos) {
        return toAppendTo.append(cf.format(number)).append(df.format(number));
    }

    @Override
    public Number parse(String source, ParsePosition parsePosition) {
        throw new UnsupportedOperationException();
    }
}

原理说明

DecimalFormat的模式字符串实际上包含正负两个子模式,负子模式是可选的。如果只写"0.0#",等价于"0.0#;-0.0#",也就是说对负数会自动加上“-”。所以直接使用DecimalFormat,是无法区分“0”和“正数”的——它们都会共用正子模式,而正子模式默认没有“+”。

那么,如何给正数加上“+”?答案是利用ChoiceFormat来做一个分段映射:

  • 当数值在 [0.0, ChoiceFormat.nextDouble(0.0)) 区间时,对应空字符串 ""。细心的读者会注意到,ChoiceFormat.nextDouble(0.0) 是大于0的最小浮点数,所以这个区间实际上只包含0.0本身。
  • 当数值大于等于 ChoiceFormat.nextDouble(0.0) 时,对应 "+"。这就覆盖了所有正数。
  • 负数呢?交给DecimalFormat自带的负子模式处理就好,ChoiceFormat对负数会返回空字符串(因为负无穷到0不在上述两个区间内,默认取第一个或最后一个索引),不会干扰负号。

换句话说,ChoiceFormat负责决定是否加上“+”前缀,而DecimalFormat负责处理数值的小数位数和负号。两者组合,正好实现了“零无符号、正数带+、负数带-”的效果。

如果对ChoiceFormat的边界行为有疑问,可以查阅文档:它的限制数组必须升序排列,未命中时会自动取最接近的边界。这里用ChoiceFormat.nextDouble(0.0)可以精确区分0与正数,是一个非常巧妙的技巧。

本文转载于:https://blog.csdn.net/weixin_30830161/article/details/118831738 如有侵犯,请联系zhengruancom@outlook.com删除。
免责声明:正软商城发布此文仅为传递信息,不代表正软商城认同其观点或证实其描述。

热门关注