0

我试图找出几种方法来为双精度值保留两位小数。目前,我尝试了以下5种方法。

  • 使用 java.math.BigDecimal
  • 使用 java.text.DecimalFormat
  • 使用 java.text.NumberFormat
  • 使用 java.util.Formatter
  • 使用 String.format

这5种方法的结果基本一致。但是,在某些情况下,java.math.BigDecimal 与其他 4 种方法的结果不同。

以双精度值100.0050D为例:

使用 java.math.BigDecimal 时,它在我的代码中返回 100.00。然而,其他 4 个方法返回 100.01。结果不一致。

实际上,使用的是RoundingMode.HALF_UP。我的问题来了:

我在下面的代码中使用 java.math.BigDecimal 来保留两位小数的双值有什么遗漏吗?

还是 java.math.BigDecimal 类中的一个小缺陷?

这个你能帮我吗。先感谢您。

另外,我不确定是否在各种JDK版本中有所不同,只是提供信息,我使用的JDK版本是1.7.0_25

代码如下:

public final class PrecisionTest {

    private PrecisionTest() {
    }

    public static String format1(double value) {

        BigDecimal bd = new BigDecimal(value);
        bd = bd.setScale(2, RoundingMode.HALF_UP);
        return bd.toString();
    }

    public static String format2(double value) {

        DecimalFormat df = new DecimalFormat("0.00");
        df.setRoundingMode(RoundingMode.HALF_UP);
        return df.format(value);
    }

    public static String format3(double value) {

        NumberFormat nf = NumberFormat.getNumberInstance();
        nf.setMaximumFractionDigits(2);
        nf.setMinimumFractionDigits(2);
        nf.setRoundingMode(RoundingMode.HALF_UP);
        nf.setGroupingUsed(false);
        return nf.format(value);
    }

    public static String format4(double value) {
        return new Formatter().format("%.2f", value).toString();
    }

    public static String format5(double value) {

        return String.format("%.2f", value).toString();
    }
}

简单的测试代码如下:

public class Main {

    public static void main(String[] args) {   

        double[] testData = new double[] { 100.123D, 1234567.897D, 100.0050D,   
                80.0051D,-100245.3658D};   

        for (double value : testData) {   
            System.out.println(PrecisionTest.format1(value));   
            System.out.println(PrecisionTest.format2(value));   
            System.out.println(PrecisionTest.format3(value));   
            System.out.println(PrecisionTest.format4(value));   
            System.out.println(PrecisionTest.format5(value));   
        }   
    }   
}
4

2 回答 2

4

100.005 的双重表示不准确,略小于 100.005:

scala> new java.math.BigDecimal(100.0050)
res0: java.math.BigDecimal = 100.0049999999999954525264911353588104248046875

因此,当您设置比例和舍入模式时,它会向下舍入到 100.00。

另一方面,使用 String 构造 BigDecimal 可以按预期工作:

scala> new java.math.BigDecimal("100.0050")
res2: java.math.BigDecimal = 100.0050

scala> res2.setScale(2, java.math.RoundingMode.HALF_UP).toString
res3: java.lang.String = 100.01
于 2013-10-27T09:06:37.250 回答
2

双[] testData = 新双[] { 100.123D, 1234567.897D, 100.0050D,
80.0051D,-100245.3658D};

问题就在这里。根本与 BigDecimal 无关。这些数字不能用浮点数准确表示。尝试从值的字符串表示中初始化您的 BigDecimal 。

于 2013-10-27T09:20:53.150 回答