int A[]={};
我正在尝试实施一个小贪婪算法,其中用户输入一定数量的钱(例如:9.25),我们输出最少量的硬币,我们需要更换它(25美分,仅10美分,5美分和1美分。)
此算法适用于10或20之类的int金额,其金额仅需要程序使用25美分硬币。
如果我尝试9.10或9.01之类的数量,我会收到运行时错误,有符号整数溢出。我理解这意味着什么,但我不明白硬币的价值怎么会突然变得如此之高。
答案 0 :(得分:3)
正如Danial Tran所说,在进行逻辑运算时最好使用int。请阅读Why not use Double or Float to represent currency?您也可以避免循环播放。
#include <stdio.h>
#include <cs50.h>
#include <math.h>
int main (void) {
printf ("Enter amount: ");
//float amount = GetFloat(); //Please refer to chqrlie's comments below.
double amount = 0.0;
scanf("%lf",&amount); //I don't know GetFloat() equivalent for double. So using scanf().
long long int amountInt = (long long int) (amount * 100.0);
int coins = 0;
if (25 <= amountInt) {
coins += (amountInt/25);
amountInt = amountInt % 25;
}
if (10 <= amountInt) {
coins += (amountInt/10);
amountInt = amountInt % 10;
}
if (5 <= amountInt) {
coins += (amountInt/5);
amountInt = amountInt % 5;
}
if (1 <= amountInt) {
coins += amountInt;
}
printf ("Coins : %d\n", coins);
}
答案 1 :(得分:1)
您的算法不正确:
例如30美分你可以用你的算法交换到:25 + 5(2个硬币)它将是10 + 10 + 10(3个硬币)。如此贪婪意味着为什么它超过25美分然后先换成25美分。
while (amount != 0) {
if (amount >= 0.25) {
amount = amount - 0.25;
coins += 1;
}
else if (amount >= 0.10) {
amount = amount - 0.10;
coins += 1;
}
else if (amount >= 0.05) {
amount = amount - 0.05;
coins += 1;
}
else {
amount = amount - 0.01;
coins += 1;
}
}
如果你想这样做。
更好的方式:
int coinTypes[] = {0.25, 0.1, 0.05, 0.01};
for (int i = 0; i < 4; i++) {
coins += floor(amount / coinTypes[i];
amount -= coins * coinsTypes[i];
}
答案 2 :(得分:1)
似乎没有人回答过这个问题
如果我尝试9.10或9.01之类的数量,我会收到运行时错误,签名整数溢出,我明白这意味着什么,但我不明白硬币的价值怎么会突然变得如此之高。 / p>
所以为了完整起见,部分作为练习:
您可以使用调试器找到原因。我复制了你的代码,发现它运行了很长时间。在启动后中断一下,发现代码冻结了重复此检查:
if (fmod(amount, 0.25) == 0) {
amount = amount - 0.25;
coins += 1;
}
在中断的那一刻amount
约为120万,硬币差不多有500万。这清楚地表明了你未能检查的一件事:消极性。你可以轻松地使用你错过了 exact 零的浮点数,因为其他人已经正确推理,不需要重复。但是如果发生这种情况,你的程序应该在amount
变为负面时感到担忧。否则,在正确的条件下,它也可以继续减去负向无穷大的方式,是的,整数溢出将发生在coins
。
答案 3 :(得分:1)
这是因为计算机代表二进制(幂为2)的小数
对于0.25,计算机可以用二进制表示它。这是因为我们可以使用2 的幂来获得0.25。
然而,对于0.10(或其他提及的面额),它们不能用2的幂表示。
假设你试图使用2的幂来获得0.1,你将无法准确地获得它。你可以靠近它。
0.1 = 0.0625(2 ^ 4)+ 0.03125(2 ^ 5)+ 0.00390625(2 ^ -8)+ ...
你将接近0.1,但你永远不会达到0.1。
Float,double每个人都有一个固定的位数来表示小数。所以它只保留那么多位,其总和将略小于0.1
如果您想采用相同的方法,您可以有两种可能的解决方案: -
- 使用(金额> 0)代替(金额!= 0),或
- 使用可以在 2的幂中轻松表达的货币,例如0.25,0.125,0.375,0.06125。
醇>
答案 4 :(得分:0)
您的算法的主要问题是无效使用fmod
函数。根据定义,fmod(num, denom)
的结果是
fmod = num - floor(num/denom) * denom
其中floor(num/denom)
是整数。
因此,fmod(9.10, 0.25) == 0.1
,fmod(9.10, 0.10) == 0.1
。
此外,使用浮点数的操作很少给出精确的结果。所以amount
永远不会0
。
答案 5 :(得分:0)
您无法使用float
类型进行计算。不是0.25的精确倍数的金额无法在float
或double
类型中准确表示。
您可以通过计算精确的分数并使用整数算术分发来解决此问题:
#include <stdio.h>
#include <math.h>
void print_coins(int coins, const char *singular, const char *plural) {
if (coins > 0)
printf(" %d %s", coins, coins > 1 ? plural : singular);
}
int main(void) {
for (;;) {
double amount;
int amountInt, coins, quarters, dimes, nickels, pennies;
printf("Enter amount: ");
if (scanf("%lf", &amount) != 1 || amount <= 0)
break;
amountInt = (int)(amount * 100.0 + 0.5);
quarters = amountInt / 25;
amountInt %= 25;
dimes = amountInt / 10;
amountInt %= 10;
nickels = amountInt / 5;
amountInt %= 5;
pennies = amountInt;
amountInt = 0;
coins = quarters + dimes + nickels + pennies;
printf("coins returned: %d:", coins);
print_coins(quarters, "quarter", "quarters");
print_coins(dimes, "dime", "dimes");
print_coins(nickels, "nickel", "nickels");
print_coins(pennies, "penny", "pennies");
printf("\n");
}
return 0;
}
注意:
float
的情况下使用+ 0.5
,更改不正确,只需{1}}:一分钱短。100.10
,float
的更改不正确:3个额外的便士。1000000.10
。这样,您就可以处理超过美国国债的金额。