2011-12-09 48 views
0

有時候,我在C++中使用浮點數時發生了一些情況,並且只將數字用作0.1的倍數,作爲for循環中的增量,實際的數字是循環迭代器並不完全是0.1的倍數,但具有不可預知的其他增加或減少1^-17數量級的微小數字。我怎樣才能避免這種情況?在使用浮點數時避免不穩定的小數字

+5

不要使用浮點來迭代? – Pubby

+0

http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html –

+0

不要使用*非精確*浮點來迭代。使用IEEE 754二進制數字時,像0.125這樣的確切數字就可以得到更好的效果(當然,只要您保持在足夠大的數字範圍內)。 – kennytm

回答

6

不要遍歷浮點數。

問題是0.1不能完全用浮點數表示。因此,您應該這樣做:

for (int i = 0; i < N; i++) 
{ 
    float f = i * 0.1f; 

    ... 
} 
+2

最好的部分是,因爲他每次都加上'0.1',即使他得到一個邏輯上應該完全可以表示的數字(例如'1.0'),他也不會有這樣的機會。所以像'for(float f = 0.0f; f <1.0; f + = 0.1f)'這樣的行可能最終只會迭代9次。 – corsiKa

7

使用整數進行迭代並在使用前乘以浮點增量。

或者找到一個十進制數學包並用它來代替浮點數。

+0

馬克死了。 – EvilTeach

1

這是關於浮標工作的excellent article。有一個涵蓋正是你們的榜樣的討論 - 0.1的增量:

for (double r=0.0; r!=1.0; r+=0.1) printf("*"); 

幾顆星莫非要打印嗎?十?運行它,並感到驚訝。代碼只是繼續打印星星,直到我們打破它。

問題在哪裏?正如我們已經知道的那樣,雙打併不是無限精確的。我們在這裏遇到的問題如下:在二進制中,0.1的表示不是有限的(因爲它在基數10中)。十進制0.1相當於二進制0.0(0011),其中圓括號中的部分永遠重複。當0.1存儲在雙變量中時,它會四捨五入到最接近的可表示值。因此,如果我們將其添加10次,結果不完全等於1。

我強烈建議閱讀整篇文章,如果你工作了很多浮點數。