贪心算法给出了可疑的结果

时间:2016-09-17 19:49:50

标签: java algorithm math greedy cs50

我正在实施一个简单的贪婪算法:

目标:使用以下硬币类型中尽可能少的硬币来回报用户的更改; Quarter (0.25), Dime (0.10), Nickel (0.05)& Penny (0.01)。

输入:用户所欠的更改金额。

输出:用于偿还用户的硬币总数。

我的代码片段如下所示:

final double quarter = 0.25d;
final double dime = 0.10d;
final double nickel = 0.05d;
final double penny = 0.01d;
double changeOwed;
int coinsUsed = 0;

/*
Code to get the user's input
*/

    while (changeOwed > 0 && changeOwed % quarter != changeOwed) {
        coinsUsed++;
        changeOwed -= quarter;
    }

    while (changeOwed > 0 && changeOwed % dime != changeOwed) {
        coinsUsed++;
        changeOwed -= dime;
    }

    while (changeOwed > 0 && changeOwed % nickel != changeOwed) {
        coinsUsed++;
        changeOwed -= nickel;
    }

    while (changeOwed > 0 && changeOwed % penny != changeOwed) {
        coinsUsed++;
        changeOwed -= penny;
    }

    System.out.println("Change remaining: "+ changeOwed);
    System.out.println("Total coins used: "+coinsUsed);

结果:

Enter change owed: 32
Change remaining: 0.0
Total coins used: 128
Enter change owed: 3.25
Change remaining: 0.0
Total coins used: 13
Enter change owed: 0.32
Change remaining: 3.469446951953614E-18
Total coins used: 4

我决定使用while循环和模运算符来完成此操作。如果changeOwed等于0,那么就不需要执行while循环,因为所有的更改都将被回收。要添加到此,如果changeOwed % COINTYPE(" COINTYPE"是任意占位符)等于changeOwed,则表示COINTYPE大于changeOwed(剩余更改量) 。在这种情况下,程序继续进行下一个循环运动较小的COINTYPE。

从上面可以看出,算法似乎产生了关于所用硬币数量的正确输出。但是,如在最后一个例子中,剩余的变化量似乎已经过时了。据我所知,由于位数有限,计算机无法进行完美的算术运算。但是, 为什么剩余的变化量从0.32急剧增加到3 +?

3 个答案:

答案 0 :(得分:2)

它不是3.它的3E-18是一个非常小的数字(0.18-zeros 3)。

这可能是由使用doubles引起的。 It's a floating point error.

如果您想避免使用BigDecimal

答案 1 :(得分:1)

3.469446951953614E-18是一个非常小的数字。它的强度

答案 2 :(得分:0)

由于您正在谈论硬币和更改,因此无需在此处使用实数。您可以使用long来计算所有内容,而不是美元数,而不是BigDecimal。