2013-11-25 60 views
1
for(float i = 40; i <= 42; i+=0.1f) 
{ 
    float offset = (i-40) * 10 * sizeof(float); 
    int wtf = offset; 
    printf("%.1f =?= %d\n", offset, wtf); 
    fseek(fin, offset, SEEK_SET); 
    fread(&tf, sizeof(float), 1, fin); 
    //printf("%.1f %.4f\n", i, tf); 
} 

輸出:從浮奇怪轉換成int

0.0 =?= 0 4.0 =?= 3 8.0 =?= 7 12.0 =?= 11 16.0 =?= 15 20.0 =?= 19 24.0 =?= 23 28.0 =?= 27 32.0 =?= 31 36.0 =?= 35 40.0 =?= 39 44.0 =?= 43 48.0 =?= 47 52.0 =?= 51 56.0 =?= 55 60.0 =?= 59 64.0 =?= 63 68.0 =?= 67 72.0 =?= 71 76.0 =?= 75 80.0 =?= 79

我不明白這一點,你能幫幫我嗎?

+0

你不瞭解什麼? – 2013-11-25 18:22:40

+1

我強烈建議您閱讀[每位計算機科學家應瞭解的浮點算術知識](http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html) –

回答

3

問題是0.1不能完全表示爲二進制浮點數。每個float的值都比您預期的要少一些,轉換爲int的數值會減少,給出的值比您預期的要少。

您可以按四捨五入到最接近的整數得到的預期值:

int wtf = std::round(offset); 
1

i = 40.1f偏移量將3.99993896這是不完全4.你的例子,如果你使用C++ 11可以使用std::round(offset)標準或圓不可用std::floor(offset + 0.5f);

浮點不能表示宇宙中的所有值,並且在某些情況下,紙張上的數學運算在浮點數上可能不正確。

0

0.1在基座2表示是

0.0001100110011001100110011001100110011... 

在分數無限地重複,正如3確實以1/3 = 0.3333333 ...基座10由於實際的浮點值只能容納有限的0011數字的數量,在近似值中必然會有誤差。

可以用基數2中的有限數字精確表示的唯一小數是那些分母是整數冪的有理數。例如,用0.125f(= 1/8 )

for(float i = 40; i <= 42; i+=0.125f) 
{ 
    float offset = (i-40) * 10 * sizeof(float); 
    int wtf = offset; 
    printf("%.1f =?= %d\n", offset, wtf); 
} 

結果值與沒有截斷誤差:

0.0 =?= 0 
5.0 =?= 5 
10.0 =?= 10 
15.0 =?= 15 
20.0 =?= 20 
25.0 =?= 25 
30.0 =?= 30 
35.0 =?= 35 
40.0 =?= 40 
45.0 =?= 45 
50.0 =?= 50 
55.0 =?= 55 
60.0 =?= 60 
65.0 =?= 65 
70.0 =?= 70 
75.0 =?= 75 
80.0 =?= 80 

這是因爲0.125基座10恰恰等於0.001基座2