4

可能重复:
将小数位移动到双精度

为什么下面的数字总和不等于0.4622?但0.46219999999999994

Double total = new Double(0.08) + new Double(0.0491) + new Double(0.3218) + 
         new Double(0.0113) + new Double(0.0); // = 0.46219999999999994

我有一个检查用户输入的应用程序。

用户输入 5 个十进制数字和一个总数。应用程序检查所有 5 个数字的总和,以 4 位小数为上限,在 komma 后面是否等于总数。

封顶它给了我0.4621不等于0.4622. 我不能使用 DecimalFormat 因为它会四舍五入。如果我明确地说,向下取整,那么在这种情况下它将失败。

关于如何解决这个问题的任何建议?

4

10 回答 10

12

尝试使用java.math.BigDecimal. 双轮结果。您只需要使用add方法,而不是 + 运算符。

于 2013-01-08T14:56:08.303 回答
5

如果需要准确的答案,请避免使用 float 和 double -- Item 48 -- Effective Java Second edition

改为使用BigDecimal

于 2013-01-08T14:56:56.110 回答
3

看起来像是浮点运算的经典案例。如果您想要精确计算,请使用java.math.BigDecimal. 看看每个计算机科学家应该知道的关于浮点运算的知识

于 2013-01-08T14:57:01.183 回答
3

当您使用浮点运算时,您还必须使用适当的舍入。

顺便说一句:当原语可以使用时,不要使用对象。

double total = 0.08 + 0.0491 + 0.3218 + 0.0113 + 0.0;
System.out.printf("%.4f%n", total);

double rounded = Math.round(total * 1e4) / 1e4;
if (rounded == 0.4622)
    System.out.println("rounded matched");

印刷

0.4622
rounded matched

正如预期的那样。

于 2013-01-08T15:00:54.867 回答
2

浮点表示是一个近似值,因此当您使用 float 和 double 时,您会遇到这些小的舍入误差。例如,如果您尝试将 0.08 转换为二进制,您将意识到您实际上无法完全做到这一点。每当您在计算中使用 double 和 float 时,都需要考虑这一点。

0.08 10 = 0.00010100011110101110... 2

一个重复的模式。因此,无论您使用多少位,都会产生舍入误差。

于 2013-01-08T14:57:20.857 回答
2

Java 中的 Double 和 float 在内部表示为二进制分数,因此在表示十进制分数时可能不精确(IEEE 标准 754)。如果您的十进制数计算需要精度,请使用Java.math.BigDecimal

于 2013-01-08T15:00:59.173 回答
1

这又是一个四舍五入的问题。你永远不应该比较双打并期望它们完全相等。而是定义一个小epsylon,并期望结果在预期答案的epsylon内。

于 2013-01-08T14:56:06.433 回答
0

任何浮点值都是不精确的。解决方案在必须显示值时使用DecimalFormat 。不,它不会四舍五入,而是最接近的值。

从 javadoc :

DecimalFormat 使用半偶数舍入(请参阅 ROUND_HALF_EVEN)进行格式化。

于 2013-01-08T14:57:11.977 回答
0

像 Double 这样的浮点数的内部表示从来都不是一个精确的表示。这就是为什么在计算过程中会出现此类错误的原因。

始终建议将此类结果格式化为逗号后的特定位数,因此您的结果将正确显示为具有 4 到 15 位或更多位数的“0.4622”。

于 2013-01-08T14:57:37.030 回答
0

也许直接检查字符串输入对您来说更可行。即检查小数点后字符的长度。

于 2013-01-08T15:00:09.207 回答