【问题标题】:Rounding oddity - what is special about "100"? [duplicate]四舍五入 - “100”有什么特别之处? [复制]
【发布时间】:2013-08-04 13:40:35
【问题描述】:

有人对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 时显示。

Edit(2):我收到的 cmets 让我意识到,这与 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 在二进制中没什么特别的)

【问题讨论】:

  • 这个问题被问到overoverover
  • 我认为马丁在问为什么它发生在 100 而不是 1000 或 10000。起初我也觉得这很奇怪。但是(大概)原因是,乘以 10 的幂不只是移位数字;它经过一些二进制乘法器,你最终得到它给你的尾数和指数。由于 10 在二进制中没有什么特别之处,因此您最终可能会得到乍看之下很奇怪的东西,例如。
  • @rampion 感谢您发布一个没有直接解决问题的 100 页文档的无用链接。

标签: rounding floating-accuracy


【解决方案1】:

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

对于简单的floating-point arithmetic,“舍入误差”在数学上是不可避免的。如果您想要准确,请使用小数类型。

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

【讨论】:

  • 我明白浮动不是真实的。我的问题是,我无法理解,为什么错误只在乘以 100 时显示,而不是在乘以 10 或 1000 时显示。
  • 加减 0 看似简单的事情,但在浮点数表示的二进制小数中,就没有这么简单了。这就是为什么你看到你的行为的本质。有人链接到一篇很棒的文章,内容是 comp sci 应该了解浮点数,我强烈推荐它。
【解决方案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 转换为 double 时的错误符号相同。

每当真正的 N * 1.1d 比 1.1 更接近 2 的最接近的次幂时,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 相互补偿(即符号相反),则不应发生这种情况。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-12-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多