1

Does anyone have an explanation for this strange rounding in haskell (GHCi, version 7.2.1). Everything seems fine unless I multiply with 100.

*Main> 1.1 
1.1

*Main> 1.1 *10
11.0

*Main> 1.1 *100
110.00000000000001

*Main> 1.1 *1000
1100.0

*Main> 1.1 *10000
11000.0

Edit: what is puzzeling me is that the rounding error only shows when multiplying with 100.

Edit(2): The comments I received made me realize, that this it totally unrelated to haskell, but a general issue with floating point numbers. Numerous questions were already asked (and answered) about floating-point number oddities, where the undelying issue typcally was confusing floats with real numbers.

Perl, python, javascript and C all report 1.1 * 100.0 = 110.00000000000001. Here is what C does

double     10.0 * 1.1 = 11.000000000000000000000000
double    100.0 * 1.1 = 110.000000000000014210854715
double          110.0 = 110.000000000000000000000000
double   1000.0 * 1.1 = 1100.000000000000000000000000

The question "why does this happen only when multiplying with 100" (even though there is a precise representation for 110.0) is still unanswered, but I suppose there is no simple answer, other than fully stepping through a floating-point multiplication (Thanks to Dax Fohl for stressing that 10 is nothing special in binary)

4

2 回答 2

4

数字 1.1 不能以二进制的有限形式表示。它看起来像 1.00011001100110011...

“舍入误差”对于简单的浮点运算在数学上是不可避免的。如果您需要准确性,请使用小数类型。

http://support.microsoft.com/kb/42980

于 2013-08-03T10:00:49.230 回答
2

“为什么只有在乘以 100 时才会发生这种情况”的问题(即使有 110.0 的精确表示)仍然没有答案,但我想除了完全单步执行浮点乘法之外,没有简单的答案

好吧,假设 IEEE 754 算术和(默认)舍入到最接近的舍入模式,我认为可能有一些事情可以不用写二进制乘法的长度来说明。

双倍1.1d是实数 1.1 的半个ULP。当你将它乘以 10、100、1000 和几个 10 的幂时,你乘以一个可以精确表示为双精度数的数字 N,并具有实数乘法 1.1 * N 的结果可以精确表示的附加属性作为一个双,也是。这使得 1.1 * N 成为浮点乘法结果的良好候选者,我们将其写为 RN(N * 1.1d)。但乘法仍然不会自动舍入到 1.1 * N:

RN(N * 1.1d) = N * 1.1d + E1 with |E1| <= 0.5 * ULP(N*1.1d)

             = N * (1.1 + E2) + E1 with |E2| <= 0.5 * ULP(1.1)

             = N * 1.1 + (N * E2 + E1)

现在的问题是如何 |N * E2 + E1| 与 ULP(N*1.1d) 相比,因为我们假设 N * 1.1 恰好是一个浮点数,如果乘法的结果(也是一个浮点数)在 N * 1.1 的 1 个 ULP 内,它必须是 N * 1.1。


简而言之,与其说是 100 有什么特别之处,倒不如说是真正的 1.1d * 100 有什么特别之处,即 1) 在低于 1) 时接近 2 的幂,并且 2) 具有与将真正的 1.1 转换为双倍时的错误。

每当真正的 N * 1.1d 比 1.1 更接近于 1 的最接近的次幂时,1.1d 与 N 的浮点乘法的结果必须恰好是 N * 1.1(我认为)。这种情况的一个例子是 N=1000,N*1.1d ~ 1100,刚好在 1024 以上。

当实数 N * 1.1d 比 1.1 比 2 更接近 2 的直接上级幂时,可能会有一个浮点数表示 N * 1.1d 比 N * 1.1 更好。但如果误差 E1 和 E2 相互补偿(即符号相反),则不应发生这种情况。

于 2013-08-03T19:08:40.853 回答