维持大量花车的总数

时间:2016-11-23 16:52:01

标签: floating-point

我的程序维护着大约50,000个浮点数的数组。这些数字的总和是一个重要的数量,在数组元素发生变化时必须保持最新。有一种明显的方法可以做到这一点,numbers是数组,total是他们的总数:

function update_number(int index, float new_value) {
    total += new_value - numbers[index];
    numbers[index] = new_value;
}

我担心浮点舍入错误会导致值total与真实总数相比漂移。这有多少问题?

1 个答案:

答案 0 :(得分:2)

尽可能精确地求和大量浮点数的最着名的算法称为Kahan summation。虽然目前的算法并不是为了允许加数来改变而编写的,但是对它进行修改是微不足道的。只需在计算初始总和后保持运行错误值,并通过添加前一个值的否定然后添加新值来更新总和。

不幸的是,如果你的很多数字都是负面的话,Kahan总和并没有提供很好的最坏情况保证......并且更新步骤保证会有。 (实际上,在经过足够的更新后,条件数将趋向于零,这意味着错误将是无限的!)因此,当您可以使用Kahan求和时,您的错误将可能小,我个人不会有机会。

另一个更好的选择是pairwise summation,它在实践中提供了非常好的精确度。在成对求和中,递归地找到数组的第一半和第二半的成对和,然后对结果求和。可以把它想象成一棵二叉树,叶子上有你的数字,每个内部节点都有两个子节点的总和,而根则是所有叶子的总和。

要将成对求和成为可更新算法,只需保留所有树节点。对于每个更新的值,更改目标叶,然后将其所有祖先重新计算回根。每次更新只需要n总和,并且{{1}}额外值可以保留。