2017-02-06 36 views
0

我需要計算一些包含常見子表達式的相當長的表達式。例如,請考慮以下兩個表達式:編譯器常見子表達式消除有效嗎?

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*ab*bc*ac*b

我正在使用MSVC編譯器,但我想他們都做幾乎相同的事情。

回答

3

通常,編譯器應該認識到這一點,並且如果啓用「快速數學」(對gcc爲-ffast-math),則執行要求的轉換。原因在於浮點運算並不完全精確,表達式評估的順序可能很重要。

例(雙打,所有的常量實際上考慮其他操作的是結果):

"1e100"+"1.0"-"1e100" results in 0.0 

"1e100"-"1e100"+"1.0" results in 1.0 

因此,編譯器將只重新排序的表達式,如果你明確允許這樣的轉變。