2013-06-13 26 views
2

我有一個ASCII「15605632.68128593」我希望 其轉換爲雙不失準確性因素 -ATOF精度與雙造成的悲痛

so 
double d; 
d=(double)atof("15605632.68128593"); 
printf("%f",d); 

printed result is 15605632.681286 

任何想法?

謝謝 - !

+4

閱讀printf的文檔...「F,F 雙參數呈圓形,並且在風格轉換爲十進制表示[ - ] ddd.ddd,其中位數小數點後的字符等於精度規格,如果精度丟失,則取爲6「 –

回答

8

很可能你沒有得到所有的尾隨小數位。嘗試printf("%.8f", d)

您也可以嘗試sscanf("15605632.68128593", "%lf", &d)來代替atof調用。

也沒有必要將atof的結果轉換爲double。這已經是雙倍了。但演員沒有傷害。

請注意 - 至少大約6年前,當我仔細查看這個時 - 許多printfscanf實現都是錯誤的,因爲它們並不像您所假設的那樣起到完美反轉的作用。 Visual C/C++和gcc在其本地實現中都遇到了問題。 This paper是一個有用的參考。

Cygwin的用gcc 4.3.4:

#include <stdio.h> 

int main(void) 
{ 
    double x; 

    sscanf("15605632.68128593", "%lf", &x); 
    printf("%.8f\n", x); 
    return 0; 
} 

然後:

# gcc foo.c 
# ./a 
15605632.68128593 
+0

它工作正常! - 謝謝基因.. –

+0

然後你應該通過點擊複選標記來接受答案。 –

1

double沒有那麼多的精度。它只能從十進制字符串到double返回十進制字符串,將15(DBL_DIGfloat.h)小數點後的位置返回十進制字符串。

編輯:雖然,一般來說,我的聲明是真實的,但在這裏似乎並不是你的問題。雖然存在不能被四捨五入的16位小數位數,但這個特定輸入可以。

3

目標:將「15605632.68128593」轉換成雙精度不失準確性

atof()實現了最好的程序可以做到的。但由於15605632.68128593(16位數字)並非,因此您的C中的可表示爲double,因此它近似爲1.560563268128593080...e+07。因此準確性失去了,儘管損失很小。

doubleTypical可以代表約2 不同的號碼。附近的候選人和OP的字符串如下所示供參考。

15605632.68128592893... previous double 
"15605632.68128593" 
15605632.68128593080... closest double 

悲痛來嘗試進行打印時,認爲什麼是印刷的x確切值。而是打印了一個四捨五入的值。使用%f說明符默認爲'。'右側的6個位置。給出報告15605632.681286,一個14位數字。

查看所有double的所有有效數字的更好方法是使用%e格式和DBL_DIGDBL_DIG是'。'的最右邊數字,用十進制指數表示法%e來顯示「往返」a所需的所有數字double(將字符串加倍爲不帶字符串差異的字符串)。由於%e始終在'。'的左側顯示1位數字,因此下面的圖顯示1 + DBL_DIG有效數字。 DBL_DIG是我的礦井和許多C環境,但它有所不同。

如果你想顯示所有的顯著數字,你需要什麼樣的資格是顯著nextafter()函數顯示下一個可表示的double。所以我們可能想要顯示至少足夠的數字來區分x和下一個x。我建議DBL_DIG + 2。儘管DBL_DIG可能就足夠了。 Details

確切值用於您"1.560563268128593e+07"程序是15605632.68128593079745769500732421875。有幾種情況需要查看所有這些數字。即使你要求很多數字,在某些時候,printf()只是給你零。

#include <stdio.h> 
#include <float.h> 
#include <tgmath.h> 

int main(int argc, char *argv[]) { 
    double x; 
    x = atof("15605632.68128593"); 
    printf("%.*le\n",DBL_DIG, x); // All digits "round-trip" string-to-double-string w/o loss 
    printf("%.*le\n",DBL_DIG + 1, x); // All the significant digit "one-way" double-string 
    printf("%.*le\n",DBL_DIG + 1, nextafter(x, 2*x)); // The next representable double 
    printf("%.*le\n",DBL_DIG + 3, x); // What happens with a few more 
    printf("%.*le\n",DBL_DIG + 30, x); // What happens if you are a bit loony 
    return 0; 
} 

1.560563268128593e+07 
1.5605632681285931e+07 
1.5605632681285933e+07 
1.560563268128593080e+07 
1.560563268128593079745769500732421875000000000e+07 
+0

是的,它只是一個印刷問題 - 但它造成了我很多問題..謝謝 –

+0

d = atof(「15605632.68128593」);這應該是x = atof(「15605632.68128593」) –

+0

@alirezasanaee謝謝 - 發佈修改 – chux