我正在使用浮点值处理C程序,下面是我的代码。
#include<stdio.h>
#include<stdlib.h>
#include<float.h>
int main()
{
int counter = 0;
float quarter = 0.25;
float dime = 0.10;
float nickel = 0.05;
float penny = 0.01;
float change = 0.00;
printf("hi, how much do i owe u?\t");
scanf("%f", &change);
while(change > 0.0)
{
if(change >= quarter)
{
change -= quarter;
printf("quarter %.2f\n", quarter);
}
else if(change >= dime)
{
change -= dime;
printf("dime %.2f\n", dime);
}
else if(change >= nickel)
{
change -= nickel;
printf("nickel %.2f\n", nickel);
}
else if(change >= penny)
{
change -= penny;
printf("penny %.2f\n", penny);
}
counter++;
}
printf("your count is %i\n", counter);
return 0;
}
输出是:
hi, how much do i owe u? .45
quarter 0.25
dime 0.10
nickel 0.05
penny 0.01
penny 0.01
penny 0.01
penny 0.01
`^C`
我必须按ctrl
c
来终止循环
上次printf("your count is %i\n", counter);
根本没有执行 - 使用<{1}}
如果我将count # of coins
类型替换为float
,则表示正常。
请帮助解决此问题
答案 0 :(得分:3)
在循环开头添加:
if (change < penny) {
printf("remaining: %.10f\n", change);
break;
}
将发出此输出:
hi, how much do i owe u? .45
quarter 0.25
dime 0.10
nickel 0.05
penny 0.01
penny 0.01
penny 0.01
penny 0.01
remaining: 0.0099999849
your count is 7
这是由内部浮点数表示引起的。存在固有错误 - 大多数浮点数没有精确的表示 - 它们只是非常好的近似值。
答案 1 :(得分:2)
帮自己一个大忙。取输入的值,乘以100,然后用全美分而不是美元进行所有计算。只有您的打印输出才能转换为美元和美分。
计算机使用整数比使用浮点数更准确。
答案 2 :(得分:0)
在循环结束时打印change
,看看它最终会变成什么。我的猜测是,由于浮点错误,它将是一个非常小的正数。您只需将while
语句更改为change > 1.e-3
或其他较小的数字即可解决此问题。
答案 3 :(得分:0)
你的循环问题是没有一个案例可以匹配。我自己,我会写ifs链的最后一个分支为
else {
/* must be the case that change >= penny */
change -= penny;
printf("penny %.2f\n", penny);
}
该评论解释了应该的情况,但如果不是这样,程序将不会失败。
如果由于某种原因你需要确定这个评论是真的(在这种情况下不是问题,但在更高风险的背景下可能是这样),你可以写
else {
assert(change >= penny);
change -= penny;
...
}
或者如果你想保留你所拥有的结构,你可以写
else if(change >= penny)
{
change -= penny;
printf("penny %.2f\n", penny);
} else {
/* ooops! This should be impossible */
fprintf(stderr, "Can't happen: change %f < penny\n", change);
exit(1);
}
或类似的东西。通过一系列if
语句,如果没有全部else
或switch without a
默认值',您应该养成自动思考“如果不可能会发生什么会发生什么”的习惯em>发生吗?“
这是一个更大的问题(并且可能有点分散注意力),但使用断言进行编程是一个非常好的习惯。如果你能说服自己“X不可能是假的”(例如pointer != NULL
或i < i_max
)那么把它写成断言。如果该断言是错误的,那么您立即在代码中发现了一个主要的逻辑错误。
最后一件事:为什么最后一次if
测试失败了?在数学运算中,它不会失败,但要记住计算机使用浮点数,其中0.01不能精确表示。因此,表示为0.01(或0.05或0.10)的数字实际上不是那个数字,而是距离数字大约1e-7的数字,这意味着您拥有的change
值将是只是< / em>低于0.01,或者只有高于0.0, 为什么change > 0.0
都可以为真,change >= 0.01
为假。