首页 > 解决方案 > 为什么在飞镖中乘以两个双精度会导致非常奇怪的数字

问题描述

谁能解释为什么结果是 252.99999999999997 而不是 253?应该使用什么来获得 253?

double x = 2.11;
double y = 0.42;
print(((x + y) * 100)); // print 252.99999999999997

我基本上是在尝试将小数点后 2 位的货币值(即 2.11 英镑)转换为便士/美分(即 211 便士)谢谢

标签: dartintdouble

解决方案


简而言之:因为许多小数双精度值不精确,并且添加不精确的值会产生更不精确的结果。这是 IEEE-754 浮点数的固有属性,这是 Dart(以及大多数其他语言和运行它们的 CPU)正在使用的。

有理数 2.11 和 0.42 都不能精确地表示为一个double值。当您编写2.11为源代码时,其含义double是最接近数学数字 2.11 的实际值。

的值2.11正好是 2.109999999999999875655021241982467472553253173828125。的值0.42正好是 0.419999999999999984456877655247808434069156646728515625。如您所见,两者都略小于您想要的值。

然后将这两个值相加,得到精确double结果 2.529999999999999804600747665972448885440826416015625。这会丢失四舍五入的最后几位数字0.42,并且由于两者都已经小于 2.11 和 0.42,因此结果现在甚至比 2.53 还要小。最后将其乘以 100,得到精确结果 252.999999999999971578290569595992565155029296875。

这与双精度值 253.0 不同。

double.toString方法不返回确切值的字符串,但它确实为不同的值返回不同的字符串,并且由于该值与 253.0 不同,因此它必须返回不同的字符串。然后它返回一个最短数字的字符串,它仍然比下一个相邻的双精度值更接近结果,这就是你看到的字符串。


推荐阅读