2011-12-09 42 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。

我强烈建议阅读整篇文章,如果你工作了很多浮点数。