我有这个功能:
int change(float c)
{
float coins[] = {0.25, 0.10, 0.05, 0.01};
int count[] = {0, 0, 0, 0};
while(c > (0.00))
{
printf("I entered here\n");
if((c-coins[0]) >= (0.00))
{
c -= coins[0];
count[0]++;
printf("-0.25, c = %.2f\n", c);
}
else if((c-coins[1]) >= (0.00))
{
c -= coins[1];
count[1]++;
printf("-0.10, c = %.2f\n", c);
}
else if((c-coins[2]) >= (0.00))
{
c -= coins[2];
count[2]++;
printf("-0.05, c = %.2f\n", c);
}
else if((c-coins[3]) >= (0.00))
{
c -= coins[3];
count[3]++;
printf("-0.01, c = %.2f\n", c);
}
}
printf("(%d) 25 cents, (%d) 10 cents, (%d) 5 cents, (%d) 1 cents\n",
count[0], count[1], count[2], count[3]);
int total = count[0] + count[1] + count[2] + count[3];
return total;
}
每当我尝试输入0.06或0.07,或任何导致它到达最后else if
子句(else if((c-coins[3]) >= (0.00))
)的浮点数时,它将导致无限循环。
然而,如果我输入0.25,0.10,0.05及其各自的完美倍数,则功能会顺利进行。 (因为它可能不会达到最后的else if
条款。)
所以当我调试(使用简单的printf
技术)时,我发现变量c
仍然进入while
循环,即使它有达到0.00。在某些情况下,它甚至会达到-0.00或-0.01(这仅在我将else if((c-coins[3]) >= (0.00))
更改为else
时才有效。
示例(假设代码中的else if
仅为else
):
输入:0.06
c-0.05, c = 0.01
c-0.01, c = -0.00 **<- WTF**
(0) 25 cents, (0) 10 cents, (1) 5 cents, (1) 1 cents
Total Coins: 2
有人向我解释这个吗?我错过了一些关于浮点数的规则吗?或者某些错误是由我的最后else if
条引起的?
注意:将上一个else if
更改为else
可能会有效,但会影响最终答案。此外,将while
条件更改为-0.00
或0.001
也不起作用。
答案 0 :(得分:6)
浮点值(通常)使用二进制表示。 coins
数组中唯一可以完全表示的部分是0.25
。所有其他值将略小于或大于正确值。这意味着对这些值的每个算术运算,即使是简单的减法,都会引入小的计算错误,这会导致比较和输出出错。
在我看来,最好的解决方案是仅使用整数类型并以美分(数百)执行所有计算。您可以使用除法和模数打印出金额。
int change(int cents)
{
int coins[] = {25, 10, 5, 1};
int count[] = {0, 0, 0, 0};
while(cents > 0)
{
if((c-coins[0]) >= 0)
{
c -= coins[0];
count[0]++;
printf("-0.25, c = %d.%02d\n", c/100, c%100);
}
/* and so on */
根据您的需要,您可能希望使用unsigned
或long
或两者。