2012-08-12 87 views
0

這是一個C代碼;pow的參數精度()C

#include<stdio.h> 
#include<math.h> 
int main() 
{ 
    double n=10.0; 
    double automatic = pow(10.0,log10(n)-log10(5.0)); 
    printf("%.9lf\n",log10(n)-log10(5.0)); 
    printf("%.9lf\n",pow(10.0,0.30102996)); 
    double manual = pow(10.0,0.30102996); 
    printf("%.9lf %lf\n",automatic, floor(automatic)); 
    printf("%.9lf %lf\n",manual,floor(manual)); 
    return 0; 
} 

輸出是:

0.301029996 
1.999999836 
2.000000000 1.000000 
1.999999836 1.000000 

從輸出I可以推斷,在POW(X,Y)Y是四捨五入到6位數字,因爲它的簽名是爲POW(雙X,雙y)的因此0.301029996變爲0.301030,這就是爲什麼自動值爲2.000000000,否則它將與手動相同。

我的問題:
1.我的感染是否正確?
2.如果第一個問題的答案是真的,那麼我們如何繞過這個舍入來獲得更準確的結果?

+0

我使用gcc所以我需要方法如何在gcc中做到這一點。 – 2012-08-12 14:48:12

回答

3

pow不輪到6位數。它使用雙精度,對於IEEE雙精度,有52位有效位(大約15位小數)。在精確度上最後一位數字可能準確或不準確,但通常很接近。

2的基數爲10的對數值的確切值接近0.301029995663981195213738894724(來源:Wolfram Alpha)。這是一個不合理的數字,因此不能完全由任何數字系統(十進制或二進制)表示。

您的結果顯示log10(n)-log10(5.0)返回的值接近於2的精確數學基數 - 10的對數,而不是0.30102996。你得到1.999999836的原因是,當你用0.30102996代替它時,你手動使得你的值不太準確。這是不是四捨五入的值,順便說一句 - 數9。

您的電話pow(10.0,log10(n)-log10(5.0))已返回的結果略低於2(如floor所示),但足夠接近以至於在9個位置輪到2。你不會比使用雙重類型更好。

所以我並不真正知道你的意思是「避免四捨五入」。如果你不想讓這個值不那麼準確,那麼不要手動將它轉到9位,並且當你複製它時肯定不會錯過任何數字;-)

+0

我明白了你的觀點;所以它意味着由於printf自動的值是2.0000000000。實際上,它不是2,但仍然是1.99999 ... – 2012-08-12 15:26:30

+0

@tendua:是的,它是從1.9999999995到2的某個地方。如果你打印'2.0 - pow(10.0,log10(n)-log10(5.0))',那麼你應該看到錯誤的幅度,儘管我認爲有可能你會得到0.取決於編譯器是否讓FPU對中間結果使用好於雙精度。 – 2012-08-12 15:35:15