为什么这种改变计数算法的行为不可靠?

时间:2014-08-25 18:47:15

标签: c greedy cs50

我对编程有点新意,只是在大学读过一门关于Python的课程,现在正在哈佛大学的CS50 OpenCourseware中学习,所以请耐心等待。

此代码编译良好,没有错误等。该程序旨在获取用户输入的更改量,并使用简单的贪婪算法返回表示该更改所需的每个美国硬币的最少数量。很简单;然而,在这里杀了我的是,由于某种原因,它并不总是算上便士。

如果我要进入" .41",我会得到" 1个宿舍,1个角钱,1个镍币和0个便士&#34 ;;进入 " 0.42"产量" 1个季度,1个维度,1个镍币和1个便士&#34 ;; 但很奇怪" .43"产生正确的" 1个季度,1个维度,1个镍币和3个便士"。

这个错误的不一致性让我难以追踪。我继续用不同的输入来浏览我脑海中的代码,试图找出问题,但这是徒劳的。

我做错了什么?

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

int main(void)
{
    printf("How much change is owed? ");
    float change = GetFloat();
    int quarters = 0;
    int dimes = 0;
    int nickels = 0;
    int pennies = 0;

    float coinArray[4] = {.25, .10, .05, .01};
    int coinNames[4] = {quarters, dimes, nickels, pennies};

    int counter(float coinArray);
        {
        int x;
        for(x = 0; x < 4; x++)
            {
            while (change >= coinArray[x])
                {
                change = change - coinArray[x];
                coinNames[x]++;
                }
            }

    }
    printf("%d Quarters, %d Dimes, %d Nickels, and %d Pennies\n",
           coinNames[0], coinNames[1], coinNames[2], coinNames[3]);
}

2 个答案:

答案 0 :(得分:3)

简单的事实是,您的计算机根本无法准确表示0.2。数学上它只有1/5,但是你的计算机不能用float代表它,就像你不能用十进制数代表1/3一样。 0.41只是41/100,这是一个最小分数,在分母中有两个五分因子 - 没有机会表示为float

准确处理货币的唯一方法是按美分而非美元计算。这样您就可以使用整数(int或更好long long代替float),并且永远不会出现舍入错误。

答案 1 :(得分:0)

如果代码与binary FP保持一致,则所有计算都必须考虑+ - * / >= ==等操作的结果可能 close ,而不是精神上做同样的事情。

change >= coinArray[x]更改为(change - coinArray[x]) > 0.005可能会在这里做到。

建议使用整数数学与简单的货币编程任务。数仙而不是美元。

尽管可行,但带有金钱的FP数学更为先进。此外,在某些平台上可以使用decimal FP