为什么“for(i = 0.1; i!= 1.0; i + = 0.1)”在i = 1.0时不会中断?
我今天参加了C考试,我被问到类似的问题:
这个程序有什么问题:
for( x = .1 ; x != 1.0 ; x += .1) printf("%f\n", x);
我无法解决它,因为我必须写一些我标记为.1
的错误。 但是,当我回到家里时,我运行这个程序,结果certificate当x
等于1.0
并且陷入无限循环时它不会中断:
$ cat exam.c #include 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.1不能精确地存储在浮点数中,检查<= 1.0
然而, 这只适用于非常有限的范围,如Cthulhu说。 我完全错过了这个问题。 因为最好使用int
并在以后划分它的值 。
<=或<不是解决方案!
在循环中使用浮点并非没有问题。 舍入误差累积。 即使使用<=
,循环也可能无法运行正确的次数。
它适用于<=1.0
(10次) ,但运行时间少于预期的<=50.0
(499次) 。
for(i = 0.1 ; i <= 50.0 ; i += 0.1) { ... }//runs 499 times, not 500!
如果遇到这个问题,这个问题可能不容易被发现。 在比较之前对其进行舍入 ( 舍入函数 )可能有所帮助,但唯一可靠的解决方案是......
在循环中使用整数作为控制变量。
永远不要使用!=
在for
循环中,当你的循环变量永远不会达到你期望的值时,它会导致很难找到错误。 总是使用<
而不是。
这是由于IEEE浮点标准。 检查维基百科
0.1 + 0.2 = 0.3 => FALSE - Expected: 0.3 | Real: 0.30000000000000004
在这里查看真实(JavaScript)演示: http : //k8.no-ip.org/stackoverflow/13542220.htm
0.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 ) ); }
在这两种情况下,您都将循环值保持为整数。