Floating point 保持大量浮动的总数

Floating point 保持大量浮动的总数,floating-point,Floating Point,我的程序维护一个大约50000个浮动的数组。这些数字的总和是一个重要的数量,必须随着数组元素的变化而保持最新。有一种明显的方法可以做到这一点,其中numbers是数组,total是它们的总数: function update_number(int index, float new_value) { total += new_value - numbers[index]; numbers[index] = new_value; } 我担心浮点舍入错误会导致值total与真实总数相

我的程序维护一个大约50000个浮动的数组。这些数字的总和是一个重要的数量,必须随着数组元素的变化而保持最新。有一种明显的方法可以做到这一点,其中
numbers
是数组,
total
是它们的总数:

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

我担心浮点舍入错误会导致值
total
与真实总数相比发生漂移。这在多大程度上是一个问题?

对大量浮点进行尽可能精确求和的最著名算法是。虽然目前的算法并不是为了允许加数改变而编写的,但是对其进行调整是很简单的。在计算初始和之后,只需保留运行中的错误值,并通过添加前一个值的求反,然后添加新值来更新和

不幸的是,如果你的很多数字都是负数,那么Kahan总和并不能提供很好的最坏情况保证。。。而更新步骤保证会有。(事实上,在足够多的更新之后,条件数将趋于零,这意味着错误将是无限的!)因此,尽管您可以使用Kahan求和,并且您的错误可能很小,但我个人不会冒险

另一个更好的选择是,它在实践中提供了非常好的精度。在成对求和中,递归地找到数组的前半部分和后半部分的成对和,然后对结果求和。把它想象成一棵二叉树,叶子代表数字,每个内部节点代表两个子节点的总和,根代表所有叶子的总和

要使成对求和成为可更新的算法,只需保留所有树节点即可。对于每个更新的值,更改目标叶,然后将其所有祖先重新计算回根。这只需要
log2(n)
每次更新的总和,以及
n
额外的值