dart - 为什么在飞镖中乘以两个双精度会导致非常奇怪的数字
问题描述
谁能解释为什么结果是 252.99999999999997 而不是 253?应该使用什么来获得 253?
double x = 2.11;
double y = 0.42;
print(((x + y) * 100)); // print 252.99999999999997
我基本上是在尝试将小数点后 2 位的货币值(即 2.11 英镑)转换为便士/美分(即 211 便士)谢谢
解决方案
简而言之:因为许多小数双精度值不精确,并且添加不精确的值会产生更不精确的结果。这是 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 不同,因此它必须返回不同的字符串。然后它返回一个最短数字的字符串,它仍然比下一个相邻的双精度值更接近结果,这就是你看到的字符串。
推荐阅读
- javascript - 你如何在 Jest 中模拟一个模块范围的变量?
- sql - SQL查询中如何计算过期日期
- c++ - 如何克服 C++ 类中方法内的“运算符不匹配”错误?
- c++ - c++混淆是使用参数化构造函数还是复制构造函数
- c++ - M1 Mac for c++ 中 VS Code 的设置问题
- apache-kafka - Kafka LDAP 和 RBAC
- c++ - 错误:架构 x86_64 的未定义符号
- api - OpenAPI - 使用 RFC 6750 Bearer Token 格式进行身份验证
- linux - 设法泄漏将函数地址放入 libc,但无法获取其他函数的地址
- c++ - 将本地 std::array 移动到传递的 std::array& 参数