我需要计算一些包含常见子表达式的相当长的表达式。例如,请考虑以下两个表达式:
double dfdx1 = 2 * (-x2 + x1 - sin(b2)*n34 + cos(b2)*sin(c2)*n24 - cos(b2)*cos(c2)*n14 + sin(b1)*m34 - cos(b1)*sin(c1)*m24 + cos(b1)*cos(c1)*m14);
double dfdx2 = -2 * (-x2 + x1 - sin(b2)*n34 + cos(b2)*sin(c2)*n24 - cos(b2)*cos(c2)*n14 + sin(b1)*m34 - cos(b1)*sin(c1)*m24 + cos(b1)*cos(c1)*m14);
除了消除所有三角函数之外,一个明显的消除是dfdx2 = -dfdx1
。问题是编译器是否会认识到这一点。我发现使用MATLAB的MuPad generate::optimize()
函数没有,这让我感到很惊讶。
更一般地说,编译器是否会在下面的示例中识别出f2 = -f1
:
double f1 = a*a + b*b - c*a - c*b;
double f2 = c*a + c*b - a*a - b*b;
或者只是消除了a*a
,b*b
,c*a
和c*b
这两个词?
我正在使用MSVC编译器,但我猜他们都做了几乎相同的事情。
答案 0 :(得分:3)
正常情况下,编译器应该认识到这一点并执行所要求的转换,如果你启用"快速数学" (-cast-math for gcc)。原因是浮点运算并不完全精确,表达式的评估顺序可能很重要。
示例(对于双精度数,所有常量实际上都被视为其他操作的结果):
"1e100"+"1.0"-"1e100" results in 0.0
"1e100"-"1e100"+"1.0" results in 1.0
因此,如果您明确允许这样的转换,编译器将只重新排序表达式。