Math 如何正确计算具有32位浮点的大型数字集的运行平均值?

Math 如何正确计算具有32位浮点的大型数字集的运行平均值?,math,floating-point,average,Math,Floating Point,Average,我正在写一个路径跟踪器,必须收集每像素大量样本的平均值。我发现1024个样本与16384个样本之间存在显著的视觉差异;16384个样本的颜色较深。我猜想这是因为16384样本图像出现浮点精度错误。我通过将每个值除以16384,然后将它们相加来平均颜色值 有没有一种方法可以在最小化舍入误差的同时,平均一组已知大小的大而难以计算的数字?最好不需要非常量内存,并且绝对不丢弃任何样本?您可能需要。当使用有限精度浮点运算对大量点求和时,这是一种将累积舍入误差降至最低的简单有效方法。由于您正在除以2的幂,并

我正在写一个路径跟踪器,必须收集每像素大量样本的平均值。我发现1024个样本与16384个样本之间存在显著的视觉差异;16384个样本的颜色较深。我猜想这是因为16384样本图像出现浮点精度错误。我通过将每个值除以16384,然后将它们相加来平均颜色值


有没有一种方法可以在最小化舍入误差的同时,平均一组已知大小的大而难以计算的数字?最好不需要非常量内存,并且绝对不丢弃任何样本?

您可能需要。当使用有限精度浮点运算对大量点求和时,这是一种将累积舍入误差降至最低的简单有效方法。

由于您正在除以2的幂,并且您的数字不是非常小,因此此步骤不应对结果的准确性产生任何影响。你只是从指数中减去14

重要的是样本中的位数

浮点数提供24位精度。如果您有2^14=16384个样本,那么当您将它们全部相加时,您将逐渐失去精度,直到24-14=10位丢失后的某一点。换句话说:在这一点上,你只保留了大约3位小数

是否可以使用int作为累加器,甚至是uint?这样,您将保留8个额外的位,是1024个和16384个采样之间差值的两倍

还有第二个完全不同的选择。我不知道你的样本范围是多少,但是如果它们的大小差不多,你可以从每个值中减去一个近似平均值,平均差异,然后在最后再加上近似平均值


通过该方法获得的收益取决于平均值的初始近似值有多好,以及值与平均值的接近程度。所以我想说,在您的情况下,它可能不太可靠。

正确吗,浮点?我很好奇这是否得到了一个比明显的“不兼容概念”更有趣的答案。我使用float是因为我试图在聚合器数组上节省内存(是的,数组中有很多float,我至少非常努力地保持在L2中)。问题不在于是否正确,而在于如何获得最佳精度。一个显而易见的实验是在试运行中切换到双打。如果它不能使变暗消失,那么从一开始就不太可能是精度问题。聚合器阵列?你所要做的就是把它们加在一个变量中(“变量”,单数),这个变量比你用来存储样本的类型大得多。要避免使用几个额外的字节,您会遇到很多麻烦。聚合器数组,因为我是成批计算光线的。:-)但由于空间原因,OP已经使用单精度浮点,因此切换到双精度浮点将比单精度Kahan提供更好的精度,所需的工作量要少得多。Kahan的算法本质上使用两个寄存器累加器将有效位的数量增加一倍——但双精度的本机尾数的宽度已经是单精度尾数的两倍多(因为指数只表示一次).Kahan非常适合,因为我的结果数组中正好有一个vec3f,而我目前并没有使用它(发射色和反射色)。那很好。(另一种选择是使用工会,这有点难看)