2016-09-30 88 views
1

我有一個多行文件。第一行包含一個整數N,後面緊跟着N行,其中每行包含一對由空格分隔的浮點數。每個浮點數都有兩個十進制數字。現在我有以下簡單的代碼,它將浮點數存儲在內存中並將它們打印出來。使用fscanf從文件中讀取浮動文件

#include <stdio.h> 
    #include <stdlib.h> 

    struct coordinates { 
     float x; 
     float y; 
    }; 

    typedef struct coordinates coords; 

    int main(int argc, char** argv) { 
     unsigned int N, i; 
     coords *points; 
     FILE *fp; 

     if (argc != 2) { 
      printf("Usage: ./bigCircle <input_file>\n"); 
      exit(0); 
     } 
     fp = fopen(argv[1], "r"); 
     N = fscanf(fp, "%u", &N); 

     points = (coords *)malloc(N*sizeof(coords)); 
     for (i=0; i<N; i++) { 
      fscanf(fp, "%f %f", &points[i].x, &points[i].y); 
      printf("%f %f\n", points[i].x, points[i].y); 
     } 

     return 0; 
    } 

的問題是,印刷浮體具有多得多的非零十進制數字,併成爲是正確的,只有當四捨五入到小數點後第二位。例如,對於一對

99999.72 -50167.43 

我的程序打印

99999.718750 -50167.429688 

這究竟是爲什麼?爲什麼我沒有得到

99999.720000 -50167.430000 

+0

因此不能表示激動,你會得到這樣的值。 – ameyCU

+0

輸入文件?但答案很簡單:浮點數並不準確。 – 4386427

+1

如果你把'float'放在bin中並且開始使用'double',這當然不會那麼糟糕。在這種情況下,你必須使用'浮動',但通常它們是20世紀教科書中的遺物。 –

回答

1

一旦數字以二進制浮點格式放入位置,它就會被數字化。您的電腦無法準確表示此號碼。因此,輸出不完全是您輸入的數字。

輸出"%f"未指定兩位小數作爲限制。因此,當它試圖輸出你讀入的值時,它會輸出更多的數字。

舉一個例子,考慮數字1.3。小數點右邊的數字,因爲它是十進制數,所以不能用二進制格式精確表示。既然你已經在你的例子中看到了,嘗試將.5(十進制)轉換爲二進制(即.1)。

作爲一個例子,考慮值1/8(2^-3)這是八進制的0.1。但是,它是十進制的.125和二進制的.001。它可以精確地表達,因爲它是2的整數次冪。除非一個數可以表示爲有限數目2的冪的和,否則它絕對不能在計算機中完全表達。

+0

但'1.5' **可以準確地表示出來,因爲'.5'是** ** **。 –

+0

@WeatherVane是的,我意識到我的錯字。這就是爲什麼我將它改爲1.3 – sabbahillel

+0

好,但你仍然提到'.5' –

0

嘗試更換:

printf("%f %f\n", points[i].x, points[i].y); 

與:

printf("%.2f %.2f\n", points[i].x, points[i].y); 

通過上述,您告訴printf打印第一。實數的X十進制數字(在本例中爲2)。第一個打印整個浮點數

1

這是一個非常簡單的 - 這是格式可以編碼的數字問題。

考慮一個整數。它可以代表的數值如0,1,2,...

但它不能代表相同的1.2,3.4號,...

這同樣適用於浮動真!它不能代表所有數字。

例如:99999.72可能未被準確編碼,因此最接近的值(可能是99999.718750)就是最終結果。

所以這些數字將四捨五入到最接近的可表示數字。

1

A float在內部表示爲二進制浮點數。當我們代表基地10多家,我們有這樣的:對於能夠準確地在基地10表示法爲代表的一批

1.625 = 1 + 6/10 + 2/100 + 5/1000 

。然後,在二進制就可以表示相同的號碼爲:

1.625(base 10) = 1 + 1/2 + 0/4 + 1/8 => 1.101(base 2) 

所以,在這裏我們有這個數字的準確的二進制表示。但是,一些數字有確切的表示以10爲基數沒有確切的表述爲float S,因爲內部表示二進制:

1.72(base 10) = 1 + 7/10 + 2/100, but 

1.72(base 10) = 1 + 1/2 + 0/4 + 1/8 + 1/16 + 1/32 + 0/64 
       + 0/128 + 0/256 + 0/512 + 1/1024 + ... 

最後部分和給出:

1.1011100001(base 2) => 1.71972656(base 10) != 1.72. 

因此,精確的二進制表示可能會大到適合可用存儲空間,或者可能沒有確切的二進制表示形式!順便提一下,1.10111(基數2)=> 1.71875(基數10)。假設你看到的是99999.718750而不是99999.72,我猜你有8位可用於你的float的小數部分。