C ++ Double to Int Conversion Complication

时间:2016-06-22 20:17:01

标签: c++

我正在尝试用C ++创建一个收银机应用程序,它要求一个项目的价格和来自客户的付款金额,然后它显示美元,四分之一,硬币和便士的变化:

#include <iostream>
using namespace std;

void printChange(int&, int&, int&, int&, int&);
void findCoins(int&, int&, int&, int&, int&);


int main()
{
    double price;
    double payment;
    char answer = 'y';
    int dollars, quarters, dimes, nickels, pennies;
    while(answer == 'y')
    {
        cout<<"Enter price of an item: "<<endl;
        cin>>price;
        cout<<"Enter payment from customer: "<<endl;
        cin>>payment;
        double change = payment - price;
        dollars = change;               //use implicit conversion
        change = change * 100;          //multiplication

        int coins = change - dollars * 100;
        findCoins(coins, quarters, dimes, nickels, pennies);

        printChange(dollars, quarters, dimes, nickels, pennies);
        cout<<"Do you have another transaction?";
        cin>>answer;
    }
    cout<<"Thanks for shopping at Albertsons!"<<endl;
    return 0;
}

void printChange(int& dol, int& q, int& d, int& n, int& p)
{
    cout<<"dollars "<<dol<<endl;
    cout<<"quarters: "<<q<<endl;
    cout<<"dimes:  "<<d<<endl;
    cout<<"nickels: "<<n<<endl;
    cout<<"pennies: "<<p<<endl;
}
void findCoins(int& coins, int& quarters, int& dimes,
        int& nickels, int& pennies)
{
    quarters = coins/25;                //use implicit conversion
    dimes = coins % 25 / 10;            //use remainder division
    nickels = coins % 25 % 10 / 5;
    pennies = coins % 25 % 10 % 5;
}

这里的问题是我需要将更改(这是一个双倍)转换为硬币(这是一个整数),以便我可以使用模数来确定出纳员欠客户的季度,硬币,镍币和硬币的数量无论我接近什么角度问题,我都会遇到同样的错误 - 原来的双倍值减1(在某些情况下)。

E.g。

Enter price of an item: 
10
Enter payment from customer: 
10.69
dollars 0
quarters: 2
dimes:  1
nickels: 1
pennies: 3

与:相比:

Enter price of an item: 
1.26
Enter payment from customer: 
5.00
dollars 3
quarters: 2
dimes:  2
nickels: 0
pennies: 4

注意:据我所知,我可以使用fmod()而不是模数作为double值,但即使将硬币更改为double,我仍会遇到相同类型的截断错误,特别是在以下情况中:

Enter price of an item: 
45
Enter payment from customer: 
47.47
dollars 2
quarters: 1
dimes:  2
nickels: 0
pennies: 1

请注意我的一分钱(与第一个例子相同)?我对C ++比较陌生,但我有超过一年的Java经验,从double转换为int时,我从未遇到过这种奇怪的截断错误(我知道在某些情况下会丢失小数点,但是为什么在多个实例中减去整个double值恰好为1?)

我的代码有哪些更改,特别是,您是否会建议防止这种恼人的截断错误?

4 个答案:

答案 0 :(得分:3)

  

我的代码有哪些更改,特别是,您是否会建议防止这种恼人的截断错误?

永远,永远,永远,永远* 10​​0,永远 1700 ,用任何编程语言记录带有浮点值的货币值,无论出于何种原因。

如果您正在使用美元,请将它们记录为整数(最好是64位整数)分(或十分之一分;当您的代码与加油站价格一起使用时,您会感谢我)当您需要以文本方式显示它们时,将它们乘以美元金额。编写一个自定义Currency类,它将自动执行这些转换,并将金额的内部记录保留为整数定点数,但将转换为浮点数仅供显示需要时。

答案 1 :(得分:0)

@xirema是对的, 错误主要在这一行

int coins = change - dollars * 100;
虽然它的合法性,并且变化= 69和美元= 0,但之后硬币将是68。

不要这样做,最好使用int。

如果你现在想解决这个问题,这是做坏事的好方法。

float dcoins = change - (dollars * 100);
    int coins = dcoins;

答案 2 :(得分:0)

要添加到Xirema的答案中,如果您需要编写货币类时可能会考虑的事项示例,可以使用code review上的帖子作为参考。

我可能会将此特定问题归结为change - dollars * 100,默认情况下整数转换不会转。

答案 3 :(得分:0)

回合到整数。

考虑payment, price, change中的值:10.69,10.00,0.69。

典型的double可以代表完全大约2 ** 64个不同的数字。由于大多数double使用二进制表示,因此数字的精确十进制值(如1.23)不在该集合中。在这种情况下,cin>>price会将文本转换为最接近的double

text   exact double value
10.69: 10.6899999999999995026200849679298698902130126953125  
10.00: 10.00  
 0.69:  0.689999999999999946709294817992486059665679931640625

如下所示,密钥失败。我们假设change - dollars * 100导致68.99999999999998578914528479799628257751465。转换为int coins的值为68,而不是69的希望值。该值未四舍五入为最接近,但截断为零。

int coins = change - dollars * 100;

要解决这个问题,有很多方法,都有利有弊。

  1. 将FP money转换为最近最低财务单位的整数金额。然后继续进行仅使用整数的数学运算。 (con:在需要时容易忘记进行舍入)

    const double money_base_unit = 0.01;
    double change = payment - price;
    coins = round(change/money_base_unit);
    
  2. 从类似{1}}的整数钱开始,就像一分钱一样基本单位。 (con:溢出问题,基本单位的一小部分货币价值,利率/利率计算等)

  3. 使用十进制浮点类型。 (通常不可用或模拟速度慢)

  4. 使用定点类型。 (更不用说了)

  5. 使用专门为赚钱而设计的课程来处理财务上的细微差别。

  6. 对于OP,简单的解决方案是将这些货币价值适当地舍入到整数便士。