92

在 C/C++ 中,您可以设置以下代码:

double a, b, c;
...
c = (a + b) / 2;

这与以下内容完全相同:

c = (a + b) * 0.5;

我想知道哪个更好用。从根本上说,一种操作是否比另一种更快?

4

3 回答 3

65

乘法比除法快。在大学里,我被告知除法是乘法的六倍。实际的时序取决于架构,但一般来说,乘法永远不会像除法一样慢,甚至不会像除法一样慢。如果舍入误差允许,请始终优化您的代码以使用乘法。

所以在一个例子中,这通常会更慢......

for (int i=0; i<arraySize; i++) {
    a[i] = b[i] / x;
}

... 比这个 ...

y=1/x;
for (int i=0; i<arraySize; i++) {
    a[i] = b[i] * y;
}

当然,如果存在舍入误差,第二种方法会降低(一点)精度,但除非您反复计算x=1/x;,否则不太可能造成太大问题。

编辑:

仅供参考。我在谷歌上搜索了第三方的操作时间比较。

http://gmplib.org/~tege/x86-timing.pdf

查看 MUL 和 DIV 上的数字。这表示 5 到 10 倍之间的差异取决于处理器。

于 2013-07-26T14:08:49.263 回答
33

在这种情况下,编译器很可能会将除法转换为乘法,如果它“认为”它更快的话。浮点除以 2 也可能比其他浮点除法更快。如果编译器不转换它,使用乘法可能会更快,但不确定 - 取决于处理器本身。

在编译器无法确定这样做是否“安全”的情况下,手动使用乘法而不是除法的收益可能非常大(例如,0.1 不能完全存储为浮点数中的 0.1,它变为 0.10000000149011612 )。有关可作为该类别代表的 AMD 处理器的数据,请参见下文。

要判断你的编译器是否能很好地做到这一点,你为什么不写一些代码来做实验。确保编写它以便编译器不只是计算一个常量值并丢弃循环中的所有计算。

编辑:

AMD 针对 Family 15h 处理器的优化指南提供的数字分别为 42 和 6 fdivfmulSSE 版本更接近一些,DIVPS、DIVPD DIVSS 和 DIVSD(除法)为 24(单)或 27(双)周期,所有形式的乘法为 6 个周期。

从记忆中,英特尔的数字并不遥远。

于 2013-07-26T13:58:24.213 回答
29

浮点乘法通常比浮点除法花费更少的周期。但是对于文字操作数,优化器很清楚这种微优化。

于 2013-07-26T13:57:19.747 回答