C while循环不停止

时间:2013-06-22 15:50:07

标签: c while-loop cs50

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

int main(void) {

    printf("Enter your change: ");
    int pennies = 0, nickels = 0, dimes = 0, quarters = 0;
    float change = GetFloat();

    while (change > 0) {
        if (change >= 0.25) {
            quarters++;
            change -= 0.25;
        }
        else if (change >= 0.10) {
            dimes++;
            change -= 0.10;
        }
        else if (change >= 0.05) {
            nickels++;
            change -= 0.05;
        }
        else if (change >=0.01) {
            pennies++;
            change -= 0.01;
        }
        // force break
        else {
        printf("%1.2f - Num. of change left\n", change);
        break;
        }
    }
    printf("Quarters: %d\n", quarters);
    printf("Dimes: %d\n", dimes);
    printf("Nickels: %d\n", nickels);
    printf("Pennies: %d\n", pennies);
    return 0;
}

你好,我现在是C新手,我正在网上攻读哈佛大学的CS50课程。 “更改”变量似乎在不停止while循环的情况下降至0.00。这迫使我在最后键入“break”。我的代码出了什么问题?

顺便说一下,这是问题集1。

6 个答案:

答案 0 :(得分:6)

浮点数如何在计算机内存中表示存在问题。如果简而言之:并非所有数字都可以精确存储。请阅读此页面了解更多详情:http://en.wikipedia.org/wiki/Floating_point#Accuracy_problems

您可以使用此服务检查计算机中浮动的表示形式:http://www.binaryconvert.com/result_float.html

关于您的情况,我们假设您输入了0.4。这意味着它应分为0.25 + 0.1 + 0.05。并且change应该为零,但是:

0.40 == 0.4000000059604644775390625000,
 minus
0.25 == 0.2500000000000000000000000000 (exact),
 minus
0.10 == 0.1000000014901161193847656250,
 minus
0.05 == 0.0500000007450580596923828125
 is
0.00 == 0.0000000037252902984619140625

正如您所看到的,最终结果略高于零,这会阻止您的循环结束。

通常情况下,如果您需要数钱,则应使用int来计算&#34;美分&#34;。或自定义类型。或者长算术。或者其他什么,但不是浮点数,因为大多数国家的资金只需要一个点后的两个位置,因此这一点不需要浮动

答案 1 :(得分:1)

您不应使用浮点数来表示本质上是完整的数字。浮点运算是一个问题。在大多数情况下,Change永远不会等于0.你应该用整数做所有事情,它会起作用。算法看起来很好。

http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html

http://floating-point-gui.de/

答案 2 :(得分:1)

正如其他人所说,这是一个浮点问题。这是你的问题:

else if (change >=0.01) {
            pennies++;
            change -= 0.01;
        }

可能发生的事情是change最终略高于0.01,所以当你从中减去0.01时,它最终略大于零,但小于0.01,而你没有{{1处理这种可能性的条款,所以它会永远持续下去。你的if显示零,因为你将它四舍五入到小数点后两位,所以它看起来像0.00,即使它可能是0.00001或者其他东西。

答案 3 :(得分:1)

使用花车是不明智的,正如在这里多次说明的那样......

逻辑上你可以做你正在尝试的事情,我怀疑它与C中的比较和推广规则有关...但我猜这会解决你的问题:

while (change > 0.0f)

你正在比较类似的类型......

你应该改为使用int,long或long long ......并代表美分而不是美元。

答案 4 :(得分:1)

未经测试,但这是我写的方式。它使用int而不是float来避免舍入问题,对每个硬币进行表驱动计算,并进行除法而不是重复减法。

int change = GetFloat() * 100 + 0.5;
struct {const char *name; int value;} coins[] = {
    {"Quarters", 25},
    {"Dimes", 10},
    {"Nickels", 5},
    {"Pennies", 1},
};
for (int i = 0; i < 4; i++) {
    int coin = change / coins[i].value;
    change %= coins[i].value;
    printf("%s: %d\n", coins[i].name, coin);
}

答案 5 :(得分:0)

您应该使用等效的getFloat()整数,或使用整数变量进行比较。由于浮点问题,代码出错了。

    #include<math.h>  // for round
...
...
    int change = int)100 * round(getFloat());