为什么Add12和Kahan的求和算法有区别?

时间:2015-01-07 23:00:16

标签: floating-point

考虑以下函数Add12,取自CRlibm's documentation并修复了几个明显错别字:

  

ab为浮点数,然后以下方法计算两个浮点数sr,以便s完全+ r = a + bs是最接近a + b的浮点数。

void Add12Cond ( double *s , double *r, double a, double b ) {
  double z ;
  *s=a+b;
  if (ABS(a) > ABS(b)){
    z=s−a;
    *r=b−z; 
  } else {
    z=s−b;
    *r=a−z;
  }
}

这看起来与应用于ab的{​​{3}}非常相似,但有一个明显区别:Kahan的求和算法并不先于确定{{1}中的哪一个而烦恼}或a拥有最大的b。它只需要加起来(通常超过两个)。

我认为浮点运算手册邀请读者思考这个差异,但没有给出任何解释。无论如何,我已经考虑了一段时间,我仍然没有任何直觉,为什么Kahan的求和算法可以取消ABS测试(我现在没有这本书)我最近提到Kahan的求和算法,提醒我这个问题。

1 个答案:

答案 0 :(得分:4)

简而言之,Kahan求和的误差范围比Add12弱。 Kahan求和得到相对于输入绝对值之和的误差。

查看Add12,它肯定会将s计算为最接近a+b的内容。条件是确保z完全计算(casework!),因此r是“a+b的其余部分。特别是,您获得了r + s = a + b|r| <= 0.5 ulp(s)

如果我们在Add12中取错了分支,但幅度相差不超过2 epsilon,则z最多会计算0.5 ulp(z) *r },所以1 ulp(z)最多会计算错误{{1}}。因此,无条件地选择两个分支意味着我们积累的误差与我们假设的东西的ulp成比例。 Kahan求和总是假设新输入较小,因此总误差大致与输入绝对值之和成比例。

卡汉在他描述卡汉求和的original half-page paper中写下了以下内容,它向我传达了星际迷航无法对20世纪60年代的狂野乐观情绪所做的事情:

  

许多FORTRAN和。中双精度的便捷可达性   一些ALGOL编译器表明很快就会出现双精度   普遍接受作为解决方案中的独创性的替代品   数值问题。

不幸的是,这篇半页的论文没有给出任何界限或证据。 Kahan求和的误差界限见TAOCP第4.2.2节中的练习19;该练习表明,由khan求和x_1,...,x_n引起的误差受(2 epsilon + O(n epsilon ^ 2))(sum(i = 1..n)| x_i |)的限制。

我打算根据TAOCP中的设置给出一个证明,但是我已经反复和尴尬地屠杀了一段时间了。令人高兴的是,我刚发现David Goldberg did this in the appendix to "What every computer scientist should know about floating-point arithmetic."