在C++中快速划分的好方法?

Ste*_*orn 13 c++ math performance

有时我会看到并使用以下变体来快速划分C++中的浮点数.

// orig loop
double y = 44100.0;
for(int i=0; i<10000; ++i) {
double z = x / y;
}

// alternative
double y = 44100;
double y_div = 1.0 / y;

for(int i=0; i<10000; ++i) {
double z = x * y_div;
}
Run Code Online (Sandbox Code Playgroud)

但最近有人暗示这可能不是最准确的方法.

有什么想法吗?

Not*_*ure 22

在几乎每个CPU上,浮点除数是浮点乘法的几倍,因此乘以除数的倒数是一个很好的优化.缺点是有,你将失去的可能性非常某些处理器精度的一小部分-例如,在现代x86处理器,64位浮点操作实际上是使用默认的FPU模式时,使用80位,并在内部存储计算它在一个变量中关闭会导致那些额外的精度位根据你的FPU舍入模式(默认为最接近)被截断.如果你连接许多浮点运算并且不得不担心错误累积,这才真正重要.


mwi*_*ahl 8

维基百科同意这可以更快.链接的文章还包含一些可能感兴趣的其他快速划分算法.

我猜想任何工业级的现代编译器都会为你做出优化,如果它会让你获利的话.

  • 工业级编译器如果可以改变程序输出,就不会做出这样的优化; 毕竟,给出错误答案的优化是一个糟糕的优化.因为我们没有用于指定我们关心的精度的语言级机制,所以编译器可能只假设我们关心所有这些. (5认同)

dwc*_*dwc 5

你原来的

// original loop:
double y = 44100.0;

for(int i=0; i<10000; ++i) {
    double z = x / y;
}
Run Code Online (Sandbox Code Playgroud)

可以轻松优化为

// haha:
double y = 44100.0;
double z = x / y;
Run Code Online (Sandbox Code Playgroud)

而且性能还不错。;-)

编辑:人们一直对此表示不赞成,所以这不是那么有趣的版本:

如果有一种通用的方法可以在所有情况下更快地进行除法,那么您不认为编译器编写者现在可能已经发生过这种情况吗?他们当然会做的。同样,有些做FPU电路的人也不是完全愚蠢。

因此,要获得更好的性能,唯一的方法就是知道手头有什么具体情况,并为此编写最佳代码。这很可能完全浪费您的时间,因为您的程序由于某些其他原因(例如对循环不变量执行数学运算)而变慢。去寻找更好的算法来代替。