Dart,float for循环会导致奇怪的结果

时间:2017-06-15 03:23:45

标签: dart angular-dart dart-html

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

导致00000000001出现的原因是什么?

1 个答案:

答案 0 :(得分:9)

这就是双数字的工作原理。在使用与Dart相同的双精度的其他语言中,您将获得相同的结果(它们标准化为IEEE-754 64-bit floating point numbers)。

关键是,例如,89.99无法用双精度精确表示。双打是二进制数字,最多53个有效位。 在二进制中,89.99没有有限的表示,就像1/3不能有限地写成十进制数(0.3333333 ......它对于精确值来说永远不够)。

只有有限数量的双值,在整个范围内扩展,覆盖率翻倍。因此,当您尝试将“真实”数字转换为双精度数时,计算机会将最接近的双精度值转换为原始数字。

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

  

54.99000000000000198951966012828052043914794921875

然后你添加35,再次无法表示为double,双硬件选择最接近该值的两倍:

  

89.990000000000009094947017729282379150390625

由于原始54.99的不精确,这实际上是一个不同于仅仅编写89.99所选择的双倍,即:

  

89.9899999999999948840923025272786617279052734375

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

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

因此,简而言之,这就是双打的目的。在使用相同double类型的大多数其他语言中,相同的计算将得到相同的结果。