为什么这个 do while 循环不能正常工作?

Why is this do while loop not working properly?

我想让它要求用户输入一个浮点数来分配给钱,比如一美元。最小单位是一分或 0.01,所以我希望它在用户每次输入负值或零时重新提示他输入。 while 条件似乎很好。有什么问题吗?

#include <stdio.h>
#include <cs50.h>
#include <math.h>

int main(void)
{ 
    float amount = 0;
    do
    {
    printf("How much change to be returned?\n");
    amount = GetFloat();
    }
    while(amount < 0.01);
}

样本运行:

jharvard@appliance (~/Dropbox/pset1): ./greedy
How much change to be returned?
0.01
How much change to be returned?

如您所见,当我输入 1 美分时,它会重复循环。如果我输入 0.02 它可以工作,但我想知道它为什么这样做。

浮点数定义并不能使它们成为比较好的类型。

这可能是类似主题的重复

while loop does not terminate - float arithmetic

0.01 无法在浮点变量中准确表示,因此我得出结论,在您的情况下,0.01 的输入被转换为大于 0.01 常量的浮点值,因此循环不会终止输入 0.01。

要解决此问题,您可以切换到完整的货币或定点数据类型,或者更简单地更改程序以使用美分而不是美元,从而避免小数值,尤其是那些无法准确表示的小数值。 Kirhog 的回答中的另一种常用技术是在比较中使用 Epsilon,例如:

double EPSILON = 0.005;
...
while(amount < 0.01+EPSILON);

以前的答案是正确的 - 浮点值不能用二进制格式准确表示。所以你应该总是比较浮点数和一些错误值:

换行

while(amount < 0.01)

while(amount - 0.01 < EPS)

其中 EPS 常量定义为(输入任何小到可以忽略不计的数字)

const float EPS = 1e-5;