我今天参加了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
....
有人可以解释为什么会发生这种情况。
答案 0 :(得分:18)
在循环中使用浮点数不没有问题。
舍入误差累积。即使使用<=
,循环也可能无法正常运行。
适用于<=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 ) );
}
在这两种情况下,您都将循环值保持为整数。