【发布时间】:2016-01-19 14:56:55
【问题描述】:
考虑以下显示一些简单算术运算的代码
int result = 0;
result = c * (a + b) + d * (a + b) + e;
要在上面的表达式中得到结果,cpu 需要执行两个整数乘法和三个整数加法。然而,在代数上,上面的表达式可以简化为下面的代码。
result = (c + d) * (a + b) + e
这两个表达式在代数上是相同的,但是第二个表达式只包含一个乘法和三个加法。 gcc(或其他编译器)是否能够自行进行这种简单的优化。
现在假设编译器足够智能,可以进行这种简单的优化,它是否能够优化更复杂的东西,例如Trapezoidal rule(用于数值积分)。下面的示例近似于sin(x) 下的区域,其中0 <= x <= pi 的步长为 pi/4(为了简单起见很小)。请假设所有文字都是运行时变量。
#include <math.h>
// Please assume all literals are runtime variables. Have done it this way to
// simplify the code.
double integral = 0.5 * ((sin(0) + sin(M_PI/4) * (M_PI/4 - 0) + (sin(M_PI/4) +
sin(M_PI/2)) * (M_PI/2 - M_PI/4) + (sin(M_PI/2) + sin(3 * M_PI/4)) *
(3 * M_PI/4 - M_PI/2) + (sin(3 * M_PI/4) + sin(M_PI)) * (M_PI - 3 * M_PI/4));
现在上面的函数可以用梯形规则简化后写成这样。这大大减少了获得相同答案所需的乘法/除法次数。
integral = 0.5 * (1 / no_steps /* 4 in th case above*/) *
(M_PI - 0 /* Upper and lower limit*/) * (sin(0) + 2 * (sin(M_PI/4) +
sin(3 * M_PI/4)) + sin(M_PI));
【问题讨论】:
-
请提供 C/C++ 语言规范的链接。在此之前,只有两种不同语言 C 和 C++。选一个!而且您的问题对于SO来说太宽泛了。请自己做一些研究。 gcc 邮件列表可能是一个好的开始。或者你只是阅读源代码。
-
您可以随时编译并检查程序集以查看它的作用。
-
当心!当您开始考虑整数溢出时,这种代数重排通常会中断。我想不出这个特定表达式的反例,但是有很多表达式会破坏它。
-
您的第二个示例(带有浮点)不太可能被优化。浮点运算不遵守
(a-b)*c==a*c - b*c这样的代数恒等式 - 下溢会导致各种奇怪的行为。