2012-12-08 75 views
10

所以我參加了一個計算競賽,我發現了一個奇怪的錯誤。戰俘(26,2)總是會返回675,有時是674?即使正確的答案是676.這些類型的錯誤也發生在pow(26,3),pow(26,4)等 在比賽結束後進行一些調試後,我相信答案與事實int下降有關。有趣的是,這種錯誤以前從未發生過。我的電腦在Windows 8上運行mingw。GCC版本相當新,像2-3個月我相信。但是我發現如果我把這些錯誤的o1/o2/o3優化標誌奇蹟般地消失了。戰俘(26,2)總是會得到676 aka正確的答案任何人都可以解釋爲什麼?GCC C++ pow精確度

#include <cmath> 
#include <iostream> 

using namespace std; 
int main() { 
    cout<<pow(26,2)<<endl; 
    cout<<int(pow(26,2))<<endl; 
} 

帶雙打的結果很奇怪。

double a=26; 
double b=2; 
cout<<int(pow(a,b))<<endl; #outputs 675 
cout<<int(pow(26.0,2.0))<<endl; # outputs 676 
cout<<int(pow(26*1.00,2*1.00))<<endl; # outputs 676 
+2

'pow(26,2)'如26 * 26 = 676? –

+0

是的,功率在標準功率函數。 –

+0

你可以發佈你的代碼嗎?我不確定你是如何得到這些值的。 –

回答

10

函數pow對兩個浮點值進行操作,並且可以相互引發一個浮點值。這是通過近似算法完成的,因爲它需要能夠處理從最小到最大的值。

由於這是一個近似算法,它有時會價值有點不對勁。在大多數情況下,這是好的。但是,如果您有興趣獲得確切的結果,請不要使用它。

我會強烈反對忠告使用它的整數。如果第二個操作數是已知的(2,在這種情況下),用這樣做的代碼替換它很簡單,並且返回正確的值。例如:

int square(int x) 
{ 
    return x * x; 
} 

要回答這個問題實際:一些編譯器可以與其他的代碼替換調用pow,或消除它一起,當一個或兩個參數是已知的。這解釋了爲什麼你得到不同的結果。

+1

您推薦使用宏而不是函數的任何特定原因? – NPE

+1

另外,我會替換*已知*與*是已知的小整數*。如果它是大數或小數已知的,則沒有多大用處。 – NPE

+0

@NPE,我選擇了一個宏,因爲它是類型中立的,並且很容易輸入:)。當然,如果你知道這個類型,你可以定義一個函數,或者一組重載函數,甚至是一個模板函數。 – Lindydancer