0

可能重复:
Haskell 范围和浮点数

例如,当我输入

[0.1, 0.3 ..1]

我明白了:

[0.1,0.3,0.5,0.7,0.8999999999999999,1.0999999999999999]

我期望:

[0.1,0.3,0.5,0.7,0.9]
4

3 回答 3

3

尝试

map (/10) [1, 3 .. 10]

反而。


问题是浮点数使用二进制分数,而二进制分数不能精确地表示十进制分数。因此,您会遇到错误并且错误会累积。

二进制分数不能精确表示 1/5,就像十进制分数不能精确表示 1/3 一样——我们能做的最好的就是 0.33333....

[0.1, 0.3 .. 1]是简写

[0.1,
 0.1 + 0.2,
 0.1 + 0.2 + 0.2,
 0.1 + 0.2 + 0.2 + 0.2,
 0.1 + 0.2 + 0.2 + 0.2 + 0.2,
 0.1 + 0.2 + 0.2 + 0.2 + 0.2 + 0.2]

另一个问题是,当下一个元素超过限制的一半以上时,列表将在第一个等于或超过限制的元素之后停止,这就是你拥有该元素的原因。1.0999999999999999

于 2012-04-26T06:47:36.147 回答
1

该表达式[e1, e2 .. e3]被评估为enumFromThenTo e1 e2 e3,对于浮点数意味着(来自The Haskell 98 Report):

对于 Float 和 Double, enumFrom 系列的语义由上面的 Int 规则给出,除了当元素变得大于e3+i/2正增量 i 或当它们小于e3+i/2负 i 时列表终止。

这意味着浮点数的最后一个元素[e1, e2 .. e3]通常大于e3,并且可以达到e3+(e2-e1)/2 - ε

于 2012-04-26T07:20:31.397 回答
1

这是浮点数在计算机中如何表示的问题。带有浮点数的简单算术通常不会按预期运行。重复算术会累积“舍入误差”,这意味着当您重复添加数字(例如)时,结果会逐渐变差。

在某些情况下,您可以通过使用不同的数字表示来避免这些问题。例如,如果您只关心有理数,则可以使用Rational类型。所以你可以这样做:

[0.1,0.3..1] :: [Rational]

这导致:

[1 % 10,3 % 10,1 % 2,7 % 10,9 % 10,11 % 10]

这是没有舍入误差的正确答案;每个数字仅表示为两个Integers 的比率。根据您的具体情况,这可能是比使用浮点数更好的选择。

这仍然超出了上限,但这比从浮点数中得到的舍入误差更容易处理。

请注意,对于某些性能关键的浮点数可能会更快。

于 2012-04-26T07:13:59.210 回答