15

我今天参加了 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
....

有人可以解释为什么会这样。

4

6 回答 6

18

<= 或 < 不是解决方案!

在循环中使用浮点并非没有问题。舍入误差累积。即使使用<=,循环也可能不会运行正确的次数。

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

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

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

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

于 2012-11-24T16:46:09.560 回答
17

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

问题是 0.1 不能完全存储在浮点数中,更好地检查 <= 1.0

然而,这只适用于像克苏鲁所说的非常有限的范围。我完全错过了这个问题。当然最好int以后再用分它的值

于 2012-11-24T14:38:38.030 回答
3

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

于 2012-11-24T14:40:19.677 回答
2

这是由于 IEEE 浮点标准。检查维基百科

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

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

于 2012-11-24T14:54:46.723 回答
1

0.1 不能完全存储在浮点数中。浮点数包含一个近似值,您正试图将其均衡为一个精确值。

于 2012-11-24T14:39:33.903 回答
1

建议,每次你需要循环使用integers

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 ) );
}

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

于 2012-11-24T14:56:41.263 回答