我的代码中存在我找不到的错误

There is bug in my code that I just can't find

本文关键字:找不到 错误 存在 代码 我的      更新时间:2023-10-16

我正在C++类中制作一个名为"自动售货机"的程序,除了一个输出,即我使用Dollar+Quarter+Quarter时,应该是1.50美元,然后循环应该会终止,但不会。所以我希望这里可能有人看到了我看不见的东西。这个程序的功能是模拟一台自动售货机,在那里你可以放入硬币(美元、25美分、1角硬币和5美分硬币),直到你有足够的钱买糖果。当你有足够的钱时,它会给你糖果,并告诉你你能得到多少零钱作为回报。

#include <iostream>
using namespace std;
void countMoney(double change); // þetta fall sér um að telja peninga.
double changeLeft(double money_total); // þetta fall sér um að reikna út afganginn af peningnum
int main()
{
    int a = 0;
    countMoney(a);
    return 0;
}
void countMoney(double change) {
    double dollar=1.00, quarter=0.25, dime=0.10, nickel=0.05;
    double money_total=0.00;
    char answer;
    cout.setf(ios::fixed);
    cout.setf(ios::showpoint);
    cout.precision(2);
    do {
        cout << "A packet of candie costs $1.50. You have inserted $" << money_total << "." << endl;
        cout << "Please insert coins:" << endl;
        cout << "                n - Nickel" << endl
             << "                d - Dime" << endl
             << "                q - Quarter" << endl
             << "                D - Dollar" << endl;
        cin >> answer;
        if(answer == 'D')
            money_total += dollar;
        else if(answer == 'q')
            money_total += quarter;
        else if(answer == 'd')
            money_total += dime;
        else if(answer == 'n')
            money_total += nickel;
        else
            cout << "'" << answer << "' is not a valid coin." << endl;
    } while(money_total <= 1.50);
    cout << "Enjoy your candies. Your change is $" << changeLeft(money_total) << ". Please         visit again." << endl;
}
double changeLeft(double money_total) {
    double change;
    change = money_total - 1.50;
    return change;
}

你说,"当我使用美元+季度+季度时,应该是1.50美元,然后循环应该会死,但不会。"这听起来像是你想改变:

while(money_total <= 1.50);

while(money_total < 1.50);

这样当你达到1.50时循环就退出了。

不要使用浮点值处理货币值!您可能会引入舍入错误,从而导致不准确的结果。浮点运算不精确。

如果您接受货币值作为输入,请尽快将其乘以(10 * decimal places),转换为整整数美分。所以,如果你需要精确到小数点后2位,乘以100。

如果将货币显示为输出,请通过除以(10 * decimal places),尽可能晚地将分数值转换为浮点值。所以,如果你需要小数点后2位的精度,除以100。

所有的数学运算都只使用整数运算。这样,就不会损失精度,不会出现舍入误差等。

例如:

#include <iostream>
using namespace std;
void countMoney();
int changeLeft(int money_total);
int main()
{
    countMoney();
    return 0;
}
void countMoney()
{
    const int dollar = 100, quarter = 25, dime = 10, nickel = 5, penny = 1;
    int money_total = 0;
    char answer;
    cout.setf(ios::fixed);
    cout.setf(ios::showpoint);
    cout.precision(2);
    do
    {
        cout << "A packet of candie costs $1.50. You have inserted $" << (((double)money_total) / 100)  << "." << endl;
        cout << "Please insert coins:" << endl;
        cout << "                p - Penny" << endl
             << "                n - Nickel" << endl
             << "                d - Dime" << endl
             << "                q - Quarter" << endl
             << "                D - Dollar" << endl;
        cin >> answer;
        if (answer == 'D')
            money_total += dollar;
        else if (answer == 'q')
            money_total += quarter;
        else if (answer == 'd')
            money_total += dime;
        else if (answer == 'n')
            money_total += nickel;
        else if (answer == 'p')
            money_total += penny;
        else
            cout << "'" << answer << "' is not a valid coin." << endl;
    }
    while (money_total < 150);
    int change = changeLeft(money_total);
    cout << "Enjoy your candies. Your change is $" << (((double)change) / 100) << "." << endl;
    cout << "Please visit again." << endl;
}
int changeLeft(int money_total)
{
    return money_total - 150;
}

所有数字都更改为int,这样就不会有比较浮点数的问题。

更重要的是,我将<=替换为<,因为如果更改为0,也可以。

#include <iostream>
using namespace std;
void countMoney(); // þetta fall sér um að telja peninga.
int changeLeft(int money_total); // þetta fall sér um að reikna út afganginn af peningnum
int main()
{
    countMoney();
    return 0;
}
void countMoney() {
    int dollar=100, quarter=25, dime=10, nickel=5;
    int money_total=0;
    char answer;
    cout.setf(ios::fixed);
    cout.setf(ios::showpoint);
    cout.precision(2);
    do {
        cout << "A packet of candie costs $1.50. You have inserted $" << ((float)money_total) / 100 << "." << endl;
        cout << "Please insert coins:" << endl;
        cout << "                n - Nickel" << endl
             << "                d - Dime" << endl
             << "                q - Quarter" << endl
             << "                D - Dollar" << endl;
        cin >> answer;
        if(answer == 'D')
            money_total += dollar;
        else if(answer == 'q')
            money_total += quarter;
        else if(answer == 'd')
            money_total += dime;
        else if(answer == 'n')
            money_total += nickel;
        else
            cout << "'" << answer << "' is not a valid coin." << endl;
    } while(money_total < 150);
    cout << "Enjoy your candies. Your change is $" << ((float)changeLeft(money_total))/100 << ". Please visit again." << endl;
}
int changeLeft(int money_total) {
    int change;
    change = money_total - 150;
    return change;
}

循环时的条件是:

money_total <= 1.50

这意味着,一旦插入1.50,循环就不会消亡。它一直持续到超过1.50。尝试将其更改为:

money_total < 1.50
while(money_total <= 1.50)

也就是说"当总和小于或等于1.5时保持循环。"换句话说,"只有当总和大于1.5时才脱离循环"。你指的是<,而不是<=

检查两个双打是否相等(在while(money_total <= 1.50);中这样做是危险的。因此,你可以用不同的方式来做:

while (money_total < 1.51)假设0.01是的最小增量(或0.001等)

while ((money_total-1.50) < epsilon),其中epsilon可以是例如boot::epsilon。

要了解有关此问题的更多信息:比较浮点值有多危险?http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm

您应该更换

while (money_total <= 1.50)

带有

while (money_total < 1.50 - epsilon)

因为有了浮点运算的怪癖,你可以得到像1.499999999999这样的和。

在您的情况下,epsilon的选择非常简单:它应该小于最小可能的硬币,即0.01,所以这会很好:

while (money_total < 1.50 - 0.001)