Haskell:表达式[0,0.1..1]的意外输出

Haskell:表达式[0,0.1..1]的意外输出,haskell,floating-point,range-notation,Haskell,Floating Point,Range Notation,计算表达式时: *main> [0, 0.1 .. 1] 我其实在期待: [0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1] 但我很震惊地看到输出是 [0.0,0.1,0.2,0.30000000000000004,0.4000000000000001,0.5000000000000001,0.6000000000000001,0.7000000000000001,0.8,0.9,1.0] 为什么Haskell在评估时会产生这样的

计算表达式时:

*main> [0, 0.1 .. 1]
我其实在期待:

 [0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1]
但我很震惊地看到输出是

[0.0,0.1,0.2,0.30000000000000004,0.4000000000000001,0.5000000000000001,0.6000000000000001,0.7000000000000001,0.8,0.9,1.0]

为什么Haskell在评估时会产生这样的结果?

这是数值不精确的结果,这对Haskell来说并不特殊。如果无法处理浮点中固有的近似值,则可以以高性能成本使用:

> import Data.Ratio
Data.Ratio> [0,1%10.. 1%1]
[0 % 1,1 % 10,1 % 5,3 % 10,2 % 5,1 % 2,3 % 5,7 % 10,4 % 5,9 % 10,1 % 1]
为了强调这一点,下面是Python:

>>> 0.3
0.29999999999999999
这是C:

void main() { printf("%0.17f\n",0.3); }

$ gcc t.c 2>/dev/null ; ./a.out
0.29999999999999999

参考。正如它所说,浮点数字在CPU中并不精确。

可能是@TomMD的重复,@Avilo:感谢各位的澄清,但我的意思是,例如0.3….0004和.5、.6、.7都以0001结尾,而.2、.8和.9都是“圆的”,这似乎有点奇怪。它似乎并不总是不精确,我不知道我是否在解释我自己。@carlos当你学习如何表示浮点时,这将是非常有意义的。请注意,精确值是2到1的负幂的和。请务必查看“关于浮点运算的每个/应该知道的内容”