当一个相对较大的浮点值与两个相对较小的浮点值相乘时,消除错误的最佳算术顺序是什么

When multiple a relative big floating point value with two relative small floating point value, what's the best order of arithmetic to eliminate error

问题描述本身很简单,假设我有两个变量,bigscale,我只想计算:

float res = big * scale * scale;

如您所见,存在两个算术顺序:

// #1
float res = (big * scale) * scale;
// #2
float res = big * (scale * scale);

由于IEEE754单精度标准,以上两行结果不同是正常的。

现在我有一些先验知识 big 可能从 0~1000scale 可能从 02^-10. big 并不像 "eat the small" 那样“大”。并且 scale 并不是那么“小”,以至于在乘以自身时会导致下溢。那留下我的问题是,与“真实”值相比,我应该采用哪种算术顺序来获得“更小的错误”?

从精度的角度来看 - 差别不大。

为避免下溢(乘积变为0.0),使用(big * scale) * scale;因为scale * scale可能变为0。

我现在看到“...而且比例不是那么“小”,不会在乘法时导致下溢。”- 好吧。

顺序可能略有不同

由于关注的是精度而不是范围:

考虑 bigscale 中 non-zero 个有效位的数量。每个 as float 最多可以有 24 个有效二进制数字。

想法是执行 2 次乘法并避免 2 次舍入。如果可能,先做乘法。如果 big 有较少的 non-zero 位有效二进制数字,则首先执行 big * scale,否则 scale * scale.

由于 OP 问题暗示 scale 可能是 power-of-2,那么由于它只有 1 个有效二进制数字,并且如果这适用于 OP 的代码,则顺序无关紧要。

考虑到 OP 的“规模不是那么”小”,因此在乘以自身时会导致下溢,因此指数无关紧要”

因为这些是 float,请检查 FLT_EVAL_METHOD 因为这个问题可能没有实际意义,因为中间计算可能会发生在更广泛的数学中。