C 贪心程序永远运行

C 贪心程序永远运行,c,cs50,C,Cs50,我最近开发了一个简单的程序,用来获取一定数量的货币(美元),并确定满足该要求所需的最少硬币数量 #include <stdio.h> #include <cs50.h> int main(void) { // prompts for change and assigns variable owed_change that value float owed_change = -1; while (owed_change < 0 ) {

我最近开发了一个简单的程序,用来获取一定数量的货币(美元),并确定满足该要求所需的最少硬币数量

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

int main(void)
{
    // prompts for change and assigns variable owed_change that value
    float owed_change = -1;
    while (owed_change < 0 )
    {
        printf("How much change is owed?\n");
        owed_change = GetFloat();
    }
    // sets the varialble n_coins to 0
    int n_coins = 0;
    // repeats until no more change is owed
    while (owed_change != 0)
    {
        /* checks for the biggest coin that can be used and increases 
        the number of coins by 1 */
        if (owed_change >= .25)
        {
            owed_change -= .25;
            n_coins++;
        }
        else if (owed_change >= .10)
        {
            owed_change -= .10;
            n_coins++;
        }
        else if (owed_change >= .05)
        {
            owed_change -= .05;
            n_coins++;
        }
        else
        {
            owed_change -= .01;
            n_coins++;
        }
    }
    printf("%d\n", n_coins);
}
#包括
#包括
内部主(空)
{
//提示进行更改,并为变量赋值以更改该值
浮动单位变化=-1;
而(欠下的_变化<0)
{
printf(“欠多少钱?\n”);
欠下的_change=GetFloat();
}
//将变量n_硬币设置为0
int n_硬币=0;
//重复,直到没有更多的变化欠
while(欠下的更改!=0)
{
/*检查可使用的最大硬币并增加
硬币的数量减少了1*/
如果(所欠金额变化>=.25)
{
所欠金额变化-=.25;
n_硬币++;
}
否则如果(欠下的更改>=.10)
{
所欠金额变化-=.10;
n_硬币++;
}
否则如果(欠下的更改>=.05)
{
所欠金额变化-=.05;
n_硬币++;
}
其他的
{
所欠金额变化-=.01;
n_硬币++;
}
}
printf(“%d\n”,n\u个硬币);
}

该程序适用于
.25
的倍数,但适用于任何其他数字。通过测试,我发现它与变量
owed\u change
相减,并得出
-0
的结果有关,该结果满足
owed\u change!=0
。然而,通过研究,我发现作为浮点的
-0
应该充当
+0
。如果是这样的话,我还做错了什么?

对你来说,最好是把钱当作美分,把你所有的价值乘以100。原因是浮动不是精确的值;这就是为什么您的代码适用于0.25这样的浮点值,但不适用于0.1、0.05和0.01这样的较小浮点数。出于您的目的,最好使用int值

而不是:

  • 0.25美元,使用25美分
  • 0.10美元,使用10美分
  • 0.05美元,使用5美分
  • 0.01美元,使用1美分

在进行上述更改后,将
u Change
的数据类型从float更改为
int
。这会解决你的问题。

TL;DR:浮动不精确。有关技术详细信息,请参见。在处理货币时,一种选择是以美分(使用
int
s)或使用精确的十进制类型(不确定C是什么类型)或使用增量(因此,您必须检查所欠的值是否在0左右,而不是
!=0
)浮点数的相等性比较是不确定的。。。因此,
while(owed\u change!=0)
通常永远不会为真。因此,使用
while(owed_change<0.009)
或类似的东西0.25可以准确地表示为
浮动(通常),但许多其他面额都不是。很可能发生的情况是,
owned\u change
最终几乎为零,但不完全是零,因此循环继续。一般来说,你不应该使用
float
s来处理这类事情——试着使用整数美分而不是浮点数美元。因为。我建议你阅读一个更好的方法,就是使用double,但将金额保持在美分。这样,您就有了更高的精度,并且可以输入非常大或非常小的金额。将其更改为
int
变量也可以。如果您需要更高的精度,也可以使用
long int
。@MalcolmMcLean在
double
中使用美分仍然会导致问题,如果输入的数字非常大(无可否认是不现实的),或者输入了分数(除非在后面显式四舍五入为整数)。如果该值足够大,减去较小的数字可能不会改变它。