gpt4 book ai didi

c++ - 我应该对循环 float 使用乘法还是除法?

转载 作者:太空宇宙 更新时间:2023-11-04 15:01:43 24 4
gpt4 key购买 nike

众所周知,除法比乘法需要更多的时钟周期来计算。 (请参阅此处的讨论:Floating point division vs floating point multiplication。)

我已经使用 x * 0.5 而不是 x/2x * 0.125 而不是 x/8 在我的 C++ 代码中,但我想知道我应该走多远。

对于倒数时重复出现的小数(即 1/num 是循环小数),我使用除法而不是乘法(例如 x/2.2 而不是 x * 0.45454545454).

我的问题是:在迭代次数相当多的循环中,我是否应该将除数替换为它们的重复乘法对应物(即 x * 0.45454545454 而不是 x/2.2), 或者这会带来更大的精度损失吗?

编辑:我做了一些分析,我在 Visual Studio 中打开了完全优化,使用 Windows QueryPerformanceCounter() 函数来获取分析结果。

int main() {
init();
int x;
float value = 100002030.0;
start();
for (x = 0; x < 100000000; x++)
value /= 2.2;
printf("Div: %fms, value: %f", getElapsedMilliseconds(), value);
value = 100002030.0;
restart();
for (x = 0; x < 100000000; x++)
value *= 0.45454545454;
printf("\nMult: %fms, value: %f", getElapsedMilliseconds(), value);
scanf_s("");
}

结果为:Div: 426.907185ms, value: 0.000000 多:289.616415ms,值:0.000000

即使经过优化,除法也几乎是乘法的两倍。性能优势是有保证的,但它们会降低精度吗?

最佳答案

For decimals that recur when inverted (ie. 1 / num is a recurring decimal), I use division instead of multiplication (example x / 2.2 instead of x * 0.45454545454).

众所周知,22/10 不能用二进制 float 精确表示,因此您所获得的不是乘以一个稍微不准确的值,而是除以一个稍微不准确的值。

事实上,如果目的是除以 22/10 或其他一些不一定能用二进制 float 精确表示的实数值,那么在一半的情况下,乘法比除法更准确,因为它巧合的是 1/X 的相对误差小于 X 的相对误差。

另一点是,您的微基准测试遇到了次正规数,其中时序并不代表对正常 float 进行常规操作的时序,片刻之后,value 是零,这再次意味着时间并不代表乘法和除法正常数字的现实。正如 Mark Ransom 所说,您至少应该使两次测量的操作数相同:正如目前所写的那样,所有乘法都采用零操作数并得出零。此外,由于 2.20.45454545454 都有 double 类型,您的基准测试是测量 double 乘法和除法,如果您愿意实现 double 乘法的单精度除法,这 needs not involve any loss of accuracy (但您必须为 1/2.2 提供更多数字)。

但是不要让自己被愚弄去尝试修复微基准。 您不需要它,因为当 X 不能比 1/X 更精确地表示时,就没有权衡取舍。没有理由不使用乘法。

注意:您应该显式地乘以 1/X 因为 /X* (1/X) 这两个操作非常略有不同,编译器无法自行进行替换。另一方面,您不需要将 /2 替换为 * 0.5,因为任何称职的编译器都应该为您做这件事。

关于c++ - 我应该对循环 float 使用乘法还是除法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35689883/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com