【问题标题】:How can I make java.text.NumberFormat format 0.0d as “0” and not “+0”?如何使 java.text.NumberFormat 格式 0.0d 为“0”而不是“+0”?
【发布时间】:2009-03-23 15:27:24
【问题描述】:

需要带符号的结果,0.0d 除外。即:

-123.45d -> "-123.45", 123.45d -> "+123.45", 0.0d -> “0”。

我在 DecimalFormat 实例上调用 format.setPositivePrefix("+") 来强制正输入结果中的符号。

【问题讨论】:

    标签: java text formatting


    【解决方案1】:

    我确定有更优雅的方法,但看看这是否有效?

    import static org.junit.Assert.assertEquals;
    
    import java.text.ChoiceFormat;
    import java.text.DecimalFormat;
    import java.text.FieldPosition;
    import java.text.NumberFormat;
    import java.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

    否定子模式是可选的;如果不存在,则以局部减号(在大多数语言环境中为“-”)为前缀的正子模式用作负子模式

    因此new DecimalFormat("0.0#") 等价于new DecimalFormat("0.0#;-0.0#")

    所以这会给我们:-1234.51234.5

    现在,要将“+”添加到正数,我使用 ChoiceFormat

    • 0.0 <= X < ChoiceFormat.nextDouble(0.0) 将使用"" 的选择格式。 ChoiceFormat.nextDouble(0.0) 是大于 0.0 的最小数字。
    • ChoiceFormat.nextDouble(0.0) <= X < 1 将使用"+" 的选择格式。

    如果没有匹配,则使用第一个或最后一个索引,具体取决于数字 (X) 是太低还是太高。如果limit数组不是升序排列,格式化的结果会不正确。 ChoiceFormat 还接受 \u221E 等同于无穷大(INF)。

    因此

    • Double.NEGATIVE_INFINITY <= X < 0 将使用 ""
    • 1 <= X < Double.POSITIVE_INFINITY 将使用 "+"

    【讨论】:

    • 这是一种冗长而迂回的说法,ChoiceFormat 就是他正在寻找的东西吗?
    【解决方案2】:

    非常感谢大家,这里有一些非常好的想法。

    根据建议,我决定使用两种格式:zeroFormat 用于 0.0d 的特殊情况,而 nonZeroFormat 用于其余情况。我将实现隐藏在 IDisplayableValueFormatter(由自定义 UI 控件使用)后面,并且不需要遵守 NumberFormat 合同/接口。

    【讨论】:

      【解决方案3】:

      Java 有“负零”和“正零”。它们有不同的表示,但相互比较是相等的。

      如果您的正值之前必须有一个加号,但您不希望它为正零,那么您可能需要执行以下操作来临时清除前缀:

      try {
          if (val == 0.0) {
              format.setPositivePrefix("");
          }
          result = format.format(val);
      }
      finally {
          format.setPositivePrefix("+");
      }
      

      【讨论】:

        【解决方案4】:

        我只是在一个项目中遇到这个问题,我没有发现这里的任何答案特别令人满意。

        我能够做的(可能对您有用也可能不适用)是:

        // Convert negative zero to positive zero.  Even though this
        // looks like it should be a no-op, it isn't.
        double correctedValue = (value == 0.0 ? 0.0 : value);
        

        那么该值将被DecimalFormat 类正确格式化。

        Java 没有内置类似的构造,这让我感到有点惊讶。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-04-28
          • 2018-08-16
          相关资源
          最近更新 更多