Java 给出可疑结果的贪婪算法

Java 给出可疑结果的贪婪算法,java,algorithm,math,greedy,cs50,Java,Algorithm,Math,Greedy,Cs50,我正在实现一个简单的贪婪算法: 目标:使用以下硬币类型中尽可能少的硬币来偿还用户的找零;四分之一硬币(0.25)、一角硬币(0.10)、镍(0.05)和便士(0.01) 输入:欠用户的更改金额 输出:用于偿还用户的硬币总数 下面是我的代码片段: final double quarter = 0.25d; final double dime = 0.10d; final double nickel = 0.05d; final double penny = 0.01d; double change

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

目标:使用以下硬币类型中尽可能少的硬币来偿还用户的找零;四分之一硬币(0.25)、一角硬币(0.10)、镍(0.05)和便士(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);

结果:


我决定使用while循环和模运算符来实现这一点。如果
changewowed
等于0,那么就不需要执行while循环,因为所有的更改都会得到回报。此外,如果
changewowed%COINTYPE
(“COINTYPE”是一个任意占位符)等于changewowed,这将表明COINTYPE大于
changewowed
(剩余的更改量)。在这种情况下,程序继续进行下一个循环,同时循环使用较小的硬币类型


如上所述,该算法似乎能产生正确的硬币使用量输出。然而,正如上一个示例中所示,剩余的变化量似乎相差很远。我知道,由于比特数有限,计算机无法完成完美的算术运算。然而,为什么剩余的变化量从0.32大幅增加到3+?3.469446951953614E-18是一个非常小的数字。它是而不是3.0的刻度。

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

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

这可能是由于使用了
双精度


如果要避免使用此选项,请不要使用3。它的3E-18是一个非常小的数字(0.18零3)

这可能是由于使用了
双精度


如果你想避免使用这种用法,因为你谈论的是硬币和零钱,这里没有必要使用实数。您可以使用long而不是BigDecimal,并以美分(而不是美元)来计算所有内容。

因为您谈论的是硬币和零钱,所以这里不需要使用实数。代替BigDecimal,您可以只使用long,并以美分而不是美元的数量计算所有内容。

一般来说,对于货币计算,最好使用
BigDecimal
ChangeOwn%quarter!=changewowed
最好写成
changewowed>=quarter
。它的意图更清晰,运行速度更快(无分区)。它还将解决您遇到的舍入问题。接下来,尝试编写代码而不使用循环。一般来说,对于货币计算,最好使用
BigDecimal
。不会
changewowed%quarter!=changewowed
最好写成
changewowed>=quarter
。它的意图更清晰,运行速度更快(无分区)。它还可以解决取整问题。接下来,尝试编写不使用循环的代码。哦,我明白了。。。我现在觉得很傻,哈哈。那么,算法本身是否真的正确呢?问题完全在于浮点运算?事实上,我没有阅读算法,我只专注于你对问题的描述。。。我能说的是,这个问题不需要任何循环,简单的算术就可以了。哦,我明白了。。。我现在觉得很傻,哈哈。那么,算法本身是否真的正确呢?问题完全在于浮点运算?事实上,我没有阅读算法,我只专注于你对问题的描述。。。我能说的是,这个问题不需要任何循环,简单的算术就可以了。
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