当一个相对较大的浮点值与两个相对较小的浮点值相乘时,消除错误的最佳算术顺序是什么
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
问题描述本身很简单,假设我有两个变量,big
和scale
,我只想计算:
float res = big * scale * scale;
如您所见,存在两个算术顺序:
// #1
float res = (big * scale) * scale;
// #2
float res = big * (scale * scale);
由于IEEE754单精度标准,以上两行结果不同是正常的。
现在我有一些先验知识 big
可能从 0
到 ~1000
,scale
可能从 0
到 2^-10
. big
并不像 "eat the small" 那样“大”。并且 scale
并不是那么“小”,以至于在乘以自身时会导致下溢。那留下我的问题是,与“真实”值相比,我应该采用哪种算术顺序来获得“更小的错误”?
从精度的角度来看 - 差别不大。
为避免下溢(乘积变为0.0),使用(big * scale) * scale;
因为scale * scale
可能变为0。
我现在看到“...而且比例不是那么“小”,不会在乘法时导致下溢。”- 好吧。
顺序可能略有不同
由于关注的是精度而不是范围:
考虑 big
和 scale
中 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
因为这个问题可能没有实际意义,因为中间计算可能会发生在更广泛的数学中。
问题描述本身很简单,假设我有两个变量,big
和scale
,我只想计算:
float res = big * scale * scale;
如您所见,存在两个算术顺序:
// #1
float res = (big * scale) * scale;
// #2
float res = big * (scale * scale);
由于IEEE754单精度标准,以上两行结果不同是正常的。
现在我有一些先验知识 big
可能从 0
到 ~1000
,scale
可能从 0
到 2^-10
. big
并不像 "eat the small" 那样“大”。并且 scale
并不是那么“小”,以至于在乘以自身时会导致下溢。那留下我的问题是,与“真实”值相比,我应该采用哪种算术顺序来获得“更小的错误”?
从精度的角度来看 - 差别不大。
为避免下溢(乘积变为0.0),使用(big * scale) * scale;
因为scale * scale
可能变为0。
我现在看到“...而且比例不是那么“小”,不会在乘法时导致下溢。”- 好吧。
顺序可能略有不同
由于关注的是精度而不是范围:
考虑 big
和 scale
中 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
因为这个问题可能没有实际意义,因为中间计算可能会发生在更广泛的数学中。