#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。
答案 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
答案 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());