当给定值并减去直到零时,C 中的无限 while 循环

Infinite while loop in C when given value and subtracting until zero

我刚开始学习 C。我正在编写一个程序,以五角硬币、五分硬币、一角硬币和便士的形式将零钱返还给客户。由于某种原因,当 while 循环到达 0 时它不会中断。

编辑: 这个问题与 SO (Is floating point math broken?) 上的另一个问题非常相似。我会为那些寻找有关 while 循环的答案的人保留这个问题,就像我自己一样,他们不知道浮点数会导致无限 while 循环。

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

int main(void){
    float val;
    int quarters = 0;
    int dimes = 0;
    int nickels = 0;
    int pennies = 0;

    printf("How much change is due?: \n");

    val = GetFloat();

    while (val > 0){

        if (val >= 0.25){
            quarters += 1;
            val -= 0.25;
        }
        else if (val >= 0.1) {
            dimes += 1;
            val -= 0.1;
        }
        else if (val >= 0.05){
            nickels += 1;
            val -= 0.05;
        }
        else if (val >= 0.01){
            pennies += 1;
            val -= 0.01;
        }

        printf("%f \n", val);
    }

    printf("Quarters: %i\n", quarters);
    printf("Dimes: %i\n", dimes);
    printf("Nickels: %i\n", nickels);
    printf("Pennies: %i\n", pennies);

    return 0;
}

有什么处理的建议吗?

这是因为 float 无法 100% 正确地表示所有值。对于某些输入值,您的程序将以 val 大于零且小于 0.1 结束。那么你就陷入了僵局。

将打印更改为:

printf("%0.30f \n", val);

将输出:

0.009999995119869709014892578125

在我的系统上。

更好的方法是在 int 中进行计算。类似于:

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

int main(void){
    float val;
    int intval;
    int quarters = 0;
    int dimes = 0;
    int nickels = 0;
    int pennies = 0;

    printf("How much change is due?: \n");

    val = GetFloat();

    intval = roundf(100 * val);  // Multiply by 100 and convert to int

    // Use intval instead of val for the remaining code
    while (intval > 0){

        if (intval >= 25){     // note: 0.25 --> 100 * 0.25 --> 25 
            quarters += 1;     // similar for all other code below 
            intval -= 25;
        }
        else if (intval >= 10) {
            dimes += 1;
            intval -= 10;
        }
        else if (intval >= 5){
            nickels += 1;
            intval -= 5;
        }
        else if (intval >= 1){
            pennies += 1;
            intval -= 1;
        }

        printf("%d \n", intval );
    }

    printf("Quarters: %i\n", quarters);
    printf("Dimes: %i\n", dimes);
    printf("Nickels: %i\n", nickels);
    printf("Pennies: %i\n", pennies);

    return 0;
}

使用调试器检查,您会发现浮点值不准确。 在这个例子中。分配 val = (float)0.41 后,您可以在 gdb 中看到:

(gdb) p val
 = 0.409999996

死循环发生是因为最后val大于0但小于0.01

在这种情况下,最简单的解决办法就是中断。当然你可能会损失一分钱:

while (val >= 0.01){
    ...