四舍五入 – “100”有什么特别之处?
Haskell有没有人对这个奇怪的舍入有一个解释(GHCi,版本7.2.1)。 一切似乎很好,除非我乘以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
编辑:令我感到困惑的是舍入误差只有在乘以100时才显示。
编辑(2):我收到的意见让我意识到,这与haskell完全无关,但浮点数的一般问题。 许多问题已经被问到(和回答)关于浮点数奇怪的问题,其中不确定的问题典型地将浮点数与实数混淆。
Perl,Python,JavaScript和C都报告1.1 * 100.0 = 110.00000000000001
。 这是C做的
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
“为什么这只发生在乘以100”(即使有一个精确的表示110.0)仍然没有答案,但我想没有一个简单的答案,除了完全通过浮点乘法(通过感谢Dax Fohl强调10是没有什么特别的二进制)
“为什么这只发生在乘以100”(即使有一个精确的表示110.0)仍然没有答案,但我想没有简单的答案,除了完全通过浮点乘法
那么,我认为可能有些事情可以说不用写二进制乘法的长度,假定IEEE 754algorithm和(默认)圆到最近舍入模式。
双1.1d
是实数1.1的一半ULP 。 当你将它乘以10,100,1000和几个十的乘方时,你乘以一个数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)在它下面接近2的幂,2)有一个与将真正的1.1转换为double时的错误。
每一次N * 1.1d相对于最接近的2次方次幂都比1.1更接近于1,N乘1.1d的浮点乘的结果必须恰好是N * 1.1(我认为)。 这种情况的一个例子是N = 1000,N * 1.1d〜1100,刚好在1024以上。
当实数N * 1.1d相对接近于2的直接上乘幂比1.1是2时,可能有一个浮点数比N * 1.1好N * 1.1d。 但是,如果错误E1和E2相互补偿(即有相反的迹象),这不应该发生。
数字1.1不能用二进制有限forms表示。 它看起来像1.00011001100110011 …
使用简单的浮点algorithm, “舍入误差”在math上是不可避免的。 如果你想要的准确性,使用十进制数字types。