Kahan summation algorithm

In numerical analysis, theKahan summation algorithm (also known ascompensated summation) significantly reduces thenumerical error in the total obtained by adding asequence of finiteprecisionfloating point numbers, compared to the obvious approach.

该算法是数值分析中的算法,用来减少浮点数累加和的数值误差,可以在高性能计算对浮点精度要求高的过程中使用。

原理:This is done by keeping a separate running compensation (a variable to accumulate small errors). 例子中所使用的c

例子如下: 

假定我们使用六位有效数字的十进制浮点算法来累加, 第一个值:10000.0,第二个值为: 3.14159,第三个值为:2.71828。那么它们 精确和应该是 10005.85987, 四舍五入为:10005.9. 然而普通的算法,前两个数相加约分后为:10003.1. 然后再和第三个数相加约分后为 10005.8,结果错误。

例子中的计算过程如下(c 初始为0):

  y = 3.14159 - 0                   y = input[i] - c
  t = 10000.0 + 3.14159
    = 10003.1                       Many digits have been lost!
  c = (10003.1 - 10000.0) - 3.14159 This must be evaluated as written! 
    = 3.10000 - 3.14159             The assimilated part of y recovered, vs. the original full y.
    = -.0415900                     Trailing zeros shown because this is six-digit arithmetic.
sum = 10003.1                       Thus, few digits from input(i) met those of sum.


 

  y = 2.71828 - -.0415900           The shortfall from the previous stage gets included.
    = 2.75987                       It is of a size similar to y: most digits meet.
  t = 10003.1 + 2.75987             But few meet the digits of sum.
    = 10005.85987, rounds to 10005.9
  c = (10005.9 - 10003.1) - 2.75987 This extracts whatever went in.
    = 2.80000 - 2.75987             In this case, too much.
    = .040130                       But no matter, the excess would be subtracted off next time.
sum = 10005.9                       Exact result is 10005.85987, this is correctly rounded to 6 digits.


 

算法伪代码如下:

function KahanSum(input)
    var sum = 0.0
    var c = 0.0          //A running compensation for lost low-order bits.
    for i = 1 to input.length do
        y = input[i] - c    //So far, so good: c is zero.
        t = sum + y         //Alas, sum is big, y small, so low-order digits of y are lost.
        c = (t - sum) - y   //(t - sum) recovers the high-order part of y; subtracting y recovers -(low part of y)
        sum = t             //Algebraically, c should always be zero. Beware eagerly optimising compilers!
        //Next time around, the lost low part will be added to y in a fresh attempt.
    return sum


### L1-009 N个数求和浮点错误解决方案 在处理大量浮点数相加时,由于计算机内部表示浮点数的方式存在精度损失,可能会导致累积误差。这种现象通常被称为 **浮点舍入误差** 或 **数值不稳定性**[^1]。 为了减少此类问题的影响,可以采取以下几种策略: #### 方法一:Kahan Summation Algorithm 一种经典的算法用于减小浮点累加中的误差是 Kahan 补偿算法。该算法通过引入补偿变量来跟踪并修正每次加法操作中丢失的小数部分,从而显著提高结果的准确性。 以下是实现此算法的一个 Python 示例: ```python def kahan_sum(numbers): sum_value = 0.0 compensation = 0.0 # 补偿项初始化为零 for number in numbers: y = number - compensation # 提取当前值并与之前的补偿抵消 t = sum_value + y # 加入总和 compensation = (t - sum_value) - y # 计算新的补偿量 sum_value = t # 更新总和 return sum_value ``` 这种方法能够有效降低因顺序不同而产生的误差幅度[^2]。 #### 方法二:调整输入数据排列方式 如果可能的话,改变参与运算的数据序列也可以帮助缓解某些情况下特定模式引发的大规模漂移效应。比如按照绝对值从小到大依次累加往往比随机或者从头至尾简单叠加要更加稳定一些。 #### 方法三:使用更高精度的数据类型 当上述两种技术仍无法满足需求时,则考虑切换成支持更宽动态范围以及更多位数的有效数字表达形式的语言特性或第三方库(如Python里的decimal模块)。不过需要注意的是这样做会牺牲一定的执行速度与内存占用率。 综上所述,在面对大规模浮点数组合计算任务时,推荐优先尝试应用改进型求和技术手段而非单纯依赖原始朴素做法以获得更为精确可靠的结果输出[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值