我试图通过使用“贪婪算法”来确定偿还变更所需的最小硬币数量。如果用户只输入一个常数整数的倍数,我在下面编写的程序正在按预期工作。然而,当谈到处理多个硬币时,程序只会暂停。
我认为问题出在我的CountGreed函数的条件语句while
循环中。我试过找到答案,但我遇到的任何事情似乎都没有给我提供任何见解,可以指导我理解我的逻辑是什么。
我知道这是微不足道的,并且在循环中通过条件语句重复,然后将我带到所述问题。如果用户输入,0.25,0.10,0.05和0.01的倍数运行良好。例如,1.00,1.25,0.20但不是0.30,1.13,0.26等
#include "cs50.h" // Contains declaration for GetFloat()
#include <stdio.h>
#include <math.h>
float PromptChange(void); // Returns customer change in dollars
int ConvertToCents(float); // Returns a conversion from dollars to cents
int CountGreed(int); // Returns the minimum number of coins for which change can be made
int main (void)
{
float Dollars = PromptChange();
int Cents = ConvertToCents(Dollars);
int CoinCount = CountGreed(Cents);
printf("The minimum number of coins required to give back change is %i.\n", CoinCount);
return 0;
}
float PromptChange(void)
{
float Dollars;
do {
printf ("Owed change: $");
Dollars = GetFloat ();
} while (Dollars < 0);
return Dollars;
}
int ConvertToCents(float Dollars)
{
float Cents = Dollars * 100;
int IntCents = (int)roundf(Cents);
return IntCents;
}
int CountGreed(int IntCents)
{
const int Quarter = 25, Dime = 10, Nickel = 5, Penny = 1;
int SubCoinCount = 0;
int CoinCount = 0;
int Remainder = 0;
while (IntCents) {
if (IntCents >= Quarter) {
SubCoinCount = IntCents / Quarter;
CoinCount += SubCoinCount;
Remainder += IntCents % Quarter;
IntCents = Remainder;
} else if (IntCents < Quarter && IntCents >= Dime) {
SubCoinCount = IntCents / Dime;
CoinCount += SubCoinCount;
Remainder += IntCents % Dime;
IntCents = Remainder;
} else if (IntCents < Dime && IntCents >= Nickel) {
SubCoinCount = IntCents / Nickel;
CoinCount += SubCoinCount;
Remainder += IntCents % Nickel;
IntCents = Remainder;
} else if (IntCents < Nickel && IntCents >= Penny) {
SubCoinCount = IntCents / Nickel;
CoinCount += SubCoinCount;
Remainder += IntCents % Dime;
IntCents = Remainder;
}
}
return CoinCount;
}
我粘贴了整个main.c文件,以便可以清楚地看到整个程序的流程,尽管问题在于循环。我在多个编译器上尝试过这个,只是为了确保它是我的错。
答案 0 :(得分:0)
此:
else if (IntCents < Nickel && IntCents >= Penny) {
SubCoinCount = IntCents / Nickel;
CoinCount += SubCoinCount;
Remainder += IntCents % Dime;
IntCents = Remainder;
}
应该是这样的:
else if (IntCents < Nickel && IntCents >= Penny) {
SubCoinCount = IntCents / Penny; // <--- Change to Penny, or just remove
CoinCount += SubCoinCount;
Remainder += IntCents % Penny; // <--- Change to Penny
IntCents = Remainder;
}
除了硬币的面额外,你的四个if
个案是完全相同的,这意味着他们会被迫加入一个单独的职能部门。这样做是一种很好的方法,可以避免在一个或几个案例中出现这样的错误,因为你只会写一次。
我也怀疑:
Remainder += IntCents % Dime;
应该是:
Remainder = IntCents % Dime;
否则Remainder
会无休止地增加,IntCents
永远不会变为零。在这种情况下,Remainder
实际上变得不必要,您可以将结果直接分配给IntCents
。
但完全这样做的方法比较简单。这是一个建议的替代方案,供您细读:
#include <stdio.h>
// This cries out to be its own function
int coin_count(int cents, int denomination, int * remainder)
{
*remainder = cents % denomination;
return cents / denomination;
}
// Better way
int CountGreed(int IntCents)
{
static const int Quarter = 25, Dime = 10, Nickel = 5, Penny = 1;
int CoinCount = 0;
while ( IntCents > 0 ) {
if ( IntCents >= Quarter ) {
CoinCount += coin_count(IntCents, Quarter, &IntCents);
} else if ( IntCents >= Dime ) {
CoinCount += coin_count(IntCents, Dime, &IntCents);
} else if ( IntCents >= Nickel ) {
CoinCount += coin_count(IntCents, Nickel, &IntCents);
} else if ( IntCents >= Penny ) {
CoinCount += coin_count(IntCents, Penny, &IntCents);
}
}
return CoinCount;
}
// Even better way
int CountGreed2(int IntCents)
{
static const int coins[4] = {25, 10, 5, 1};
int CoinCount = 0;
for ( int i = 0; i < 4; ++i ) {
if ( IntCents >= coins[i] ) {
CoinCount += coin_count(IntCents, coins[i], &IntCents);
}
}
return CoinCount;
}
int main(void) {
printf("Coins for $1.25 (should be 5): (%d)\n", CountGreed(125));
printf("Coins for $1.00 (should be 4): (%d)\n", CountGreed(100));
printf("Coins for $0.96 (should be 6): (%d)\n", CountGreed(96));
printf("Coins for $1.25 (should be 5): (%d)\n", CountGreed2(125));
printf("Coins for $1.00 (should be 4): (%d)\n", CountGreed2(100));
printf("Coins for $0.96 (should be 6): (%d)\n", CountGreed2(96));
return 0;
}
输出:
paul@local:~/Documents/src/sandbox$ ./coins
Coins for $1.25 (should be 5): (5)
Coins for $1.00 (should be 4): (4)
Coins for $0.96 (should be 6): (6)
Coins for $1.25 (should be 5): (5)
Coins for $1.00 (should be 4): (4)
Coins for $0.96 (should be 6): (6)
paul@local:~/Documents/src/sandbox$
CountGreed2()
中对单独功能的需求不太明显,因为您只需要编写一次,但口味会有所不同。
答案 1 :(得分:0)
#include "cs50.h" // Contains declaration for GetFloat()
#include <stdio.h>
#include <math.h>
float PromptChange(void); // Returns customer change in dollars
int ConvertToCents(float); // Returns a conversion from dollars to cents
int CountGreed(int); // Returns the minimum number of coins for which change can be made
int main (void)
{
float Dollars = PromptChange();
int Cents = ConvertToCents(Dollars);
int CoinCount = CountGreed(Cents);
printf("The minimum number of coins required to give back change is %d.\n",
CoinCount);
return 0;
}
float PromptChange(void)
{
float Dollars;
do {
printf ("Owed change: $");
Dollars = GetFloat ();
} while (Dollars < 0);
return Dollars;
}
// the original function ConvertToCents()
// will usually return an incorrect value
// typically off by 1
// This is because float values often cannot exactly represent
// the desired value
int ConvertToCents(float Dollars)
{
float Cents = Dollars * 100.0f; // note all values should be float
int IntCents = floor(Cents+.5f); // round up to whole penny
return IntCents;
}
int CountGreed(int IntCents)
{
const int Quarter = 25, Dime = 10, Nickel = 5, Penny = 1;
int CoinCount = 0;
int Remainder = IntCents; // get working value
// note following using integer divides
CoinCount = Remainder / Quarter; // max quarters
Remainder = Remainder % Quarter; // update working value
CoinCount += Remainder / Dime; // max dimes
Remainder = Remainder % Dime; // update working value
CoinCount += Remainder / Nickle; // max nickles
Remainder = Remainder % Nickle; // update working value
CoinCount += Remainder; // final pennys
return CoinCount;
}