【问题标题】:What is the most numerically precise method for dividing sums or differences?除以和或差的最精确的数值方法是什么?
【发布时间】:2016-12-20 06:54:44
【问题描述】:

考虑(a-b)/(c-d) 操作,其中abcd 是浮点数(即,double 在 C++ 中键入)。 (a-b)(c-d) 都是 (sum-correction) 对,如 Kahan summation algorithm。简而言之,这些 (sum-correction) 对的特殊之处在于,sum 包含的值相对于correction 中的值较大。更准确地说,correction 包含因数值限制而在求和期间不适合 sum 的内容(double 类型中的尾数为 53 位)。

考虑到上述数字的特殊性,计算(a-b)/(c-d) 的最精确的数字方法是什么?

额外问题:最好将结果也设为 (sum-correction),就像在 Kahan 求和算法中一样。所以要找到(e-f)=(a-b)/(c-d),而不仅仅是e=(a-b)/(c-d)

【问题讨论】:

    标签: algorithm floating-point sum numeric division


    【解决方案1】:

    Dekker (1971)div2 算法是一个很好的方法。

    它需要一个mul12(p,q) 算法,该算法可以精确地计算一对u+v = p*q。 Dekker 使用一种称为 Veltkamp 拆分的方法,但如果您可以访问 fma 函数,那么更简单的方法是

    u = p*q
    v = fma(p,q,-u)
    

    实际的除法看起来像(我不得不更改一些符号,因为 Dekker 使用加法对而不是减法):

    r   = a/c
    u,v = mul12(r,c)
    s   = (a - u - v - b + r*d)/c
    

    总和r+s(a-b)/(c-d) 的精确近似值。

    更新:假设减法和加法是左关联的,即

    s = ((((a-u)-v)-b)+r*d)/c
    

    这是有效的,因为如果我们让 rr 成为 r 计算中的错误(即 r + rr = a/c 完全正确),那么由于 u+v = r*c 完全正确,我们有 rr*c = a-u-v 完全正确,因此 (a-u-v-b)/c(a-b)/c 的校正项给出了相当好的近似。

    最终的r*d 出现是由于以下原因:

    (a-b)/(c-d) = (a-b)/c * c/(c-d) = (a-b)/c *(1 + d/(c-d)) 
                = [a-b + (a-b)/(c-d) * d]/c
    

    现在r 也是(a-b)/(c-d) 的一个相当好的初始近似值,因此我们将其替换为[...],因此我们发现(a-u-v-b+r*d)/c(a-b)/(c-d) 校正项的一个很好的近似值

    【讨论】:

    • return r+s 是指 e=rf=-s 表达式中的 (e-f)=(a-b)/(c-d) 吗?还是有错误,确实是e=rf=s(不否定s)?
    • 结果应该是r+s = (a-b)/(c-d)
    • 我还没有检查过这个方法(需要大量时间来深入思考),但是fma() 的东西非常有用,+1。基本上,(a - u - v - b + r*d) 不会丢失精度,还是这里期望 Kahan 求和?
    • 所以我已经深入思考,现在我明白了除了添加r*d之外的所有内容:它如何使结果在数字上更精确?
    • 我已经为r*d的来源添加了解释
    【解决方案2】:

    对于微小的修正,也许可以考虑

    (a - b) / (c - d) = a/b (1 - b/a) / (1 - c/d) ~ a/b (1 - b/a + c/d)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-02-15
      • 1970-01-01
      • 2019-05-03
      • 2022-01-27
      • 2010-09-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多