当前位置: 首页 > 知识库问答 >
问题:

贪婪硬币计数中的整数溢出

阳修永
2023-03-14
#include <stdio.h>
#include <cs50.h>
#include <math.h>

int main (void) { 

    printf ("Enter amount: ");
    float amount = GetFloat();
    int coins = 0;

    while (amount != 0) {

        if (fmod(amount, 0.25) == 0) {
            amount = amount - 0.25;
            coins += 1;
        }

        else if (fmod(amount, 0.10) == 0) {
            amount = amount - 0.10;
            coins += 1;
        }

        else if (fmod(amount, 0.05) == 0) {
            amount = amount - 0.05;
            coins += 1;
        }

        else {
            amount = amount - 0.01;
            coins += 1;
        }
    }

    printf ("Coins : %d\n", coins);
}

我正在尝试实现一个小的贪婪算法,在这个算法中,用户输入一定数量的钱(例如:9.25),我们输出的硬币数量最少,我们可以兑换(25美分、10美分、5美分和1美分)。

该算法适用于整数金额,如10或20,以及只需要程序使用25美分硬币的金额。

如果我尝试9.10或9.01这样的数值,就会得到一个运行时错误,即有符号整数溢出。我明白这意味着什么,但我不明白硬币的价值怎么会突然这么高。

共有3个答案

郑茂材
2023-03-14

这是因为计算机用二进制表示小数(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。

浮点数,双数每个人都有一个固定的位数来表示小数。因此,它将只保留这些位,其总和将略小于0.1

如果你想遵循同样的方法,你可以有两种可能的解决方案:-

  1. 使用(数量)
杜绍元
2023-03-14

似乎没有人回答这个问题

如果我尝试像9.10或9.01这样的数量,我会得到一个运行时错误,有符号整数溢出,我理解它的意思,但我不明白硬币的价值怎么会突然变得这么高。

因此,为了完整性,部分作为练习:

您可以使用调试器找到原因。我复制了你的代码,发现它运行很长时间。在启动后中断它,显示代码冻结,重复此检查:

if (fmod(amount, 0.25) == 0) {
    amount = amount - 0.25;
    coins += 1;
}

在中断的那一刻金额约为-120万,硬币近500万。这清楚地表明了一件你没有检查的事情:消极性。浮点数很容易丢失精确的零,正如其他人正确推理的那样,无需重复。但是如果发生这种情况,您的程序应该在amount变为负值时感到担心。否则,在正确的条件下,它可能会继续向负无穷大方向减法,是的,硬币中会发生整数溢出。

竺承望
2023-03-14

正如Danial Tran所说,在执行逻辑操作时最好使用int。请阅读为什么不使用Double或Float来表示货币?也可以避免while循环。

#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);
}
 类似资料:
  • 问题是用硬币、一角硬币、五分硬币和一便士来换零钱,并且使用最少的硬币总数。在四个面值分别是硬币、一角硬币、五分硬币和一便士的特殊情况下,我们有c1=25、c2=10、c3=5和c4=1。 如果我们只有四分之一硬币、一角硬币和一分硬币(没有五分镍币)可供使用,贪婪算法将使用六枚硬币——四分之一硬币和五便士——兑换30美分,而我们可以使用三枚硬币,即三个一角硬币。 给定一组面额,我们如何判断贪婪方法是

  • 首先,是的,这是我的硬件,我觉得很难,所以我真的很感激一些指导。 我需要证明对于当

  • 我试图在硬币兑换问题中实现贪婪方法,但需要降低时间复杂度,因为编译器不会接受我的代码,而且由于我无法验证,我甚至不知道我的代码是否正确。函数应返回进行更改所需的注释总数。如果无法获得给定金额的更改,则返回-1。如果金额等于面额列表中可用的货币之一,则返回1。

  • 以人民币的硬币为例,假设硬币数量足够多。要求将一定数额的钱兑换成硬币。要求兑换硬币数量最少。 思路说明: 这是用贪婪算法的典型应用。在本例中用python来实现,主要思想是将货币金额除以某硬币单位,然后去整数,即为该硬币的个数;余数则做为向下循环计算的货币金额。 这个算法的问题在于,得出来的结果不一定是最有结果。比如,硬币单位是[1,4,6],如果将8兑换成硬币,按照硬币数量最少原则,应该兑换成为

  • 我理解硬币兑换问题的贪婪算法(用尽可能少的硬币支付特定金额)是如何工作的——它总是选择面额最大但不超过剩余金额的硬币——并且它总是为特定的硬币组找到正确的解决方案。 但对于某些硬币集,贪婪算法会失败。例如,对于集合和总和30,贪婪算法首先选择25,剩下5,然后选择5个1,总共6枚硬币。但是,对于最少数量的硬币,解决方案是选择15枚硬币两次。 一组硬币必须满足什么条件,才能让贪婪算法找到所有总数的最

  • 贪婪的变更算法是通过选择可用的最高面额硬币进行变更,直到达到它试图进行的变更量。令人惊讶的是,这种算法实际上是以最有效的方式改变美国和欧元硬币面额的! 然而,贪婪的算法有时会在做出改变时失败。假设我们有面额[25,15,1],并试图赚31美分。贪婪的算法会选择25,1,1,1,1,1,1 (7硬币),而31美分实际上可以制作成15,15,1(3枚硬币)。 我想知道的是,是否有一种方法可以让贪婪算法