Kahan 算法中用加法代替减法

发布于 2024-12-20 12:54:35 字数 868 浏览 1 评论 0原文

这是来自维基百科的 Kahan 求和算法

function KahanSum(input)
    var sum = 0.0
    var c = 0.0
    for i = 1 to input.length do
        y = input[i] - c    // why subtraction?
        t = sum + y
        c = (t - sum) - y
        sum = t
    return sum

是否有特定原因使用减法(而不是添加)?如果我在c的计算中交换操作数,我可以用加法代替吗?不知何故,这对我来说更有意义:

function KahanSum(input)
    var sum = 0.0
    var c = 0.0
    for i = 1 to input.length do
        y = input[i] + c    // addition instead of subtraction
        t = sum + y
        c = y - (t - sum)   // swapped operands
        sum = t
    return sum

或者浮点加法和减法之间是否存在一些我还不知道的奇怪差异?

另外,原算法中的(t - sum) - yt - sum - y有什么区别吗?无论如何,括号不是多余的吗?因为 - 是左关联的?

This is the Kahan summation algorithm from Wikipedia:

function KahanSum(input)
    var sum = 0.0
    var c = 0.0
    for i = 1 to input.length do
        y = input[i] - c    // why subtraction?
        t = sum + y
        c = (t - sum) - y
        sum = t
    return sum

Is there a specific reason why it uses subtraction (as opposed to addition)? If I swap the operands in the computation of c, can I use addition instead? Somehow, that would make more sense to me:

function KahanSum(input)
    var sum = 0.0
    var c = 0.0
    for i = 1 to input.length do
        y = input[i] + c    // addition instead of subtraction
        t = sum + y
        c = y - (t - sum)   // swapped operands
        sum = t
    return sum

Or is there some weird difference between floating point addition and subtraction I don't know about yet?

Also, is there any difference between (t - sum) - y and t - sum - y in the original algorithm? Aren't the parenthesis redundant, since - is left-associative, anyway?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

心的憧憬 2024-12-27 12:54:36

据我所知,您的方法与维基百科中的方法完全相同。唯一的区别是 c 的符号(及其含义)颠倒了。在维基百科算法中,c 是总和的“错误”部分; c=0.0001 意味着总和比应有的要大一些。在您的版本中,c 是对总和的“修正”; c=-0.0001 表示总和应该稍微小一些。

我认为括号是为了可读性。它们是为我们服务的,而不是为机器服务的。

As far as I can tell, your method is exactly equivalent to the one from Wikipedia. The only difference is that the sign of c -- and therefore its meaning -- is reversed. In the Wikipedia algorithm, c is the "wrong" part of the sum; c=0.0001 means that the sum is a little bigger than it should be. In your version, c is the "correction" to the sum; c=-0.0001 means that the sum should be made a little smaller.

And I think the parentheses are for readability. They're for us, not the machine.

不必了 2024-12-27 12:54:36

你的两种算法是等价的。执行期间唯一的区别是 c 的符号。它使用加法的原因是因为在 Kahan 的版本中,c 代表误差,通常是正确值减去计算值。

从括号指定运算顺序的意义上来说,括号是绝对必要的。事实上,正是它们使这个算法发挥作用!

当减法是左关联时(就像在大多数语言中一样),a - b - c 的计算结果为 (a - b) - c,因此两者是相同的。但 Kahan 算法中的减法是 a - (b - c),并且不应将其计算为 a - b + c

浮点加法和减法不具有关联性。对于在标准算术中等效的表达式,根据执行运算的顺序,您可能会得到不同的结果。

为了清楚起见,我们使用 3 个小数位的精度。这意味着如果我们得到 4 位数字的结果,我们必须对其进行四舍五入。
现在将 (a - b) - c 与数学上等效的 a - (b + c) 进行比较,以获取某些特定值:

(998 - 997) - 5 = 1 - 5 = -4

因此

998 - (997 + 5) = 998 - Round(1002)
                = 998 - 1000 = -2

第二种方法不太准确。

在 Kahan 算法中,tsumy 相比通常相对较大。因此,您经常会遇到如上例所示的情况,如果不按正确的顺序执行操作,您将得到不太准确的结果。

Your two algorithms are equivalent. The only difference during execution will be the sign of c. The reason it uses addition is because in Kahan's version, c represents the error, which is conventionally the correct minus the computed value.

In the sense that parentheses specify the order of operations, the parentheses are absolutely necessary. In fact, they are what makes this algorithm work!

When subtraction is left-associative, as it is in most languages, a - b - c evaluates as (a - b) - c so the two are the same. But the subtraction in the Kahan algorithm is a - (b - c), and that should not be evaluated as a - b + c.

Floating-point addition and subtraction are not associative. For expressions that are equivalent in standard arithmetic, you may get different results depending on the order in which you perform the operations.

Let's work with 3 decimal digits of precision, for the sake of clarity. This means that if we get a result with 4 digits, we have to round it.
Now compare (a - b) - c with the mathematically equivalent a - (b + c) for some specific values:

(998 - 997) - 5 = 1 - 5 = -4

with

998 - (997 + 5) = 998 - Round(1002)
                = 998 - 1000 = -2

So the second approach is less accurate.

In the Kahan algorithm, t and sum will usually be relatively large compared to y. So you often get a situation like in the example above where you would get a less accurate result if you don't do the operations in the correct order.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文