2

我知道计算机不能精确地表示非整数。所以当我在java中添加2个双打时:

724.64d + 1000d

控制台打印出 1724.6399999999999

724.64d + 100d但为什么724.64d + 10000d

控制台分别打印出 824.64 和 10724.64?

有没有办法知道当我添加 2 个双打时在什么条件下,总和是确切的数字?

我问的原因是因为我们的旧程序使用 double 进行计算。并使用双重比较来验证数字。例如:假设总数为1849.64,所有输入量加起来必须等于总数,即1849.64

input 1: 724.64
input 2: 1125

将不起作用,因为总和将为 1849.6399999999999

但是如果我们像下面这样输入就可以了,总和是 1849.64

input 1: 24.64
input 2: 1825

那么如何找到那些有效的组合呢?请注意,我无权访问这个特定的非常旧的程序。当验证失败时,我们必须像第二个输入组合一样手动找到一个走动。谢谢。

4

5 回答 5

2
BigDecimal bigDecimal = new BigDecimal(724.64);
bigDecimal = bigDecimal.add(new BigDecimal(1000.0));
System.out.println(bigDecimal.floatValue());<--Works fine 
System.out.println(bigDecimal.doubleValue());<--Works as mentioned in Question

输出:

1724.64
1724.6399999999999

在第一种情况下,它之所以起作用,是因为narrowing primitive conversion发生了。但是对于浮点数,您将不得不接受并接受它。

正如我所说的它对原语有效的原因

double d = 724.64;
double d1 = 1000.0;
System.out.println(d + d1);
System.out.println((float) (d + d1));

输出:

1724.64
1724.6399999999999
于 2012-10-26T20:34:55.170 回答
1

浮点数不代表十进制的数字,而是在二进制系统中,显然它们只有有限的精度,因此十进制系统表示的确切值与浮点数可以表示的值之间存在不匹配。你不能期望它会这样做。

于 2012-10-26T20:31:13.520 回答
1

与其尝试确定导致精确或不精确计算的条件,不如考虑在这些情况下使用BigDecimal

于 2012-10-26T20:36:46.023 回答
1

要回答您的最后一个问题,如果小数部分是 2 的负幂,例如零、1/ 2、1 /4、1/16 ......情况,就像您发布的情况一样,如果您用来将它们转换为十进制的 API(例如 System.out.println())进行舍入或截断,并且该值足够接近以使舍入或截断产生预期的答案。

于 2012-10-26T20:56:55.593 回答
0

如果比较是问题,作为一种解决方法,我建议将字符串中的数字格式化为小数点后 2 位并四舍五入,然后比较字符串:

        double expectNum = 1849.64;
        double resultNum = 1849.639999;

        String expectedString = String.format("%.2g%n", expectNum);
        String resultString = String.format("%.2g%n", resultNum);

        if(expectedString.equals(resultString)){
           //result matched
           //return true;
        }else{
           //return false;
        }
于 2012-10-26T20:37:33.563 回答