Dart 省道,循环浮动将导致奇怪的结果

Dart 省道,循环浮动将导致奇怪的结果,dart,angular-dart,dart-html,Dart,Angular Dart,Dart Html,是什么导致0000000000 1出现的?这就是双倍数字的工作原理。在使用与Dart相同双精度的其他语言中,您会得到相同的结果(它们被标准化为Dart) 问题的关键是,例如,89.99不能准确地用双打的精度来表示。double是最多有53个有效位的二进制数。 在二进制中,89.99没有有限的表示形式,就像1/3不能有限地写为十进制数一样(0.3333333…对于精确的值来说永远不够) 只有有限数量的双倍值,分布在整个双倍覆盖范围内。因此,当你试图将一个“实数”转换成一个双精度数时,计算机会将其舍

是什么导致0000000000 1出现的?

这就是双倍数字的工作原理。在使用与Dart相同双精度的其他语言中,您会得到相同的结果(它们被标准化为Dart)

问题的关键是,例如,89.99不能准确地用双打的精度来表示。double是最多有53个有效位的二进制数。 在二进制中,89.99没有有限的表示形式,就像1/3不能有限地写为十进制数一样(0.3333333…对于精确的值来说永远不够)

只有有限数量的双倍值,分布在整个双倍覆盖范围内。因此,当你试图将一个“实数”转换成一个双精度数时,计算机会将其舍入到与原始数最接近的双精度值

即使是54.99也不精确。
54.99
的实际双精度值是最接近数学数字54.99(又名5499/100)的双精度值:

54.9900000000000198951966012828052043914794921875

然后再加上35,这同样不能表示为double,double硬件会选择与该值最接近的double:

899900000000009094947017729282379150390625

由于原版54.99的不精确性,这实际上是一个不同于仅用于编写
89.99
的双精度版本,即:

89.98999999999488409230252727866172790522734375

当您将double转换为字符串时,拾取表示的算法实际上很聪明。它选择最短的十进制表示形式,其中数值将四舍五入为原始的双精度值

因此,由于
54.99+35
89.99
不同,它们需要有不同的字符串表示形式。字符串
89.99
显然是后者,因此
54.99+35
需要更多的数字来区分自己。这就是尾随
00000000000001
的来源


简言之,双打就是这样做的。在使用相同双精度类型的大多数其他语言中,相同的计算将给出相同的结果。

浮点数有限精度?
for(int i=0; i<10; i++) {
    priceValue.add(54.99 + i*5);
    print(54.99 + i*5);
}
js_primitives.dart:30 54.99
js_primitives.dart:30 59.99
js_primitives.dart:30 64.99000000000001
js_primitives.dart:30 69.99000000000001
js_primitives.dart:30 74.99000000000001
js_primitives.dart:30 79.99000000000001
js_primitives.dart:30 84.99000000000001
js_primitives.dart:30 89.99000000000001
js_primitives.dart:30 94.99000000000001
js_primitives.dart:30 99.99000000000001