为什么" for(i = 0.1; i!= 1.0; i + = 0.1)"在i = 1.0时不会中断吗?

时间:2012-11-24 14:36:59

标签: c floating-point

我今天参加了C考试,我被问到类似的问题:

  

这个程序有什么问题:

for( x = .1 ; x != 1.0 ; x += .1)
    printf("%f\n", x);

我无法解决它,因为我必须写一些我将.1标记为错误的内容。但是,当我回到家中时,我运行了这个程序,结果发现当x等于1.0并且陷入无限循环时它不会中断:

$ cat exam.c
#include <stdio.h>

int main(int argc, char **argv)
{
    float x;

    for(x = .1 ; x != 1.0 ; x += .1)
        printf("%f\n", x);

    return 0;
}
$ gcc exam.c -o exam
$ ./exam
0.100000
0.200000
0.300000
0.400000
0.500000
0.600000
0.700000
0.800000
0.900000
1.000000 <- ?
1.100000
1.200000
1.300000
1.400000
1.500000
....

有人可以解释为什么会发生这种情况。

6 个答案:

答案 0 :(得分:18)

&lt; =或&lt;不是解决方案!

在循环中使用浮点数没有问题。 舍入误差累积。即使使用<=,循环也可能无法正常运行

适用于<=1.0 (10 times) ,但运行时间比<=50.0 (499 times) 少一倍。

 for(i = 0.1 ; i <= 50.0 ; i += 0.1)
       { ... }//runs 499 times, not 500!

如果遇到这个问题,这个问题可能不容易被发现。 在比较之前对其进行舍入( rounding functions )可能有所帮助,但唯一可靠的解决方案是......

在循环中使用整数作为控制变量。

答案 1 :(得分:17)

这是家庭作业的典型问题。

问题是0.1不能精确地存储在浮点数中更好地检查&lt; = 1.0

然而这只适用于非常有限的范围,如Cthulhu所说。我完全错过了这个问题。原因最好使用int并稍后将其值除以

答案 2 :(得分:3)

永远不要在!=循环中使用for,当循环变量永远不会达到您期望的值时,它会导致很难找到错误。总是使用<代替。

答案 3 :(得分:2)

这是由于IEEE浮点标准。 Check Wikipedia

0.1 + 0.2 = 0.3 => FALSE - Expected: 0.3 | Real: 0.30000000000000004

在此处查看真实(JavaScript)演示:http://k8.no-ip.org/stackoverflow/13542220.htm

答案 4 :(得分:1)

0.1无法准确存储在浮点数中。浮点数包含近似值,您尝试将其均衡为精确值。

答案 5 :(得分:1)

建议,每次需要循环时都使用整数

int x;
float y = 0;
for( x = 1; x < 11; x += 1){
    y += 0.1; 
    printf("%f\n", y);
}

或者您也可以使用它:

for( x = 1; x < 11; x += 1){
    printf("%f\n", ( x / 10.0 ) );
}

在这两种情况下,您都将循环值保持为整数。