我正在尝试用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?)
我的代码有哪些更改,特别是,您是否会建议防止这种恼人的截断错误?
答案 0 :(得分:3)
我的代码有哪些更改,特别是,您是否会建议防止这种恼人的截断错误?
永远,永远,永远,永远* 100,永远 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;
要解决这个问题,有很多方法,都有利有弊。
将FP money转换为最近最低财务单位的整数金额。然后继续进行仅使用整数的数学运算。 (con:在需要时容易忘记进行舍入)
const double money_base_unit = 0.01;
double change = payment - price;
coins = round(change/money_base_unit);
从类似{1}}的整数钱开始,就像一分钱一样基本单位。 (con:溢出问题,基本单位的一小部分货币价值,利率/利率计算等)
使用十进制浮点类型。 (通常不可用或模拟速度慢)
使用定点类型。 (更不用说了)
使用专门为赚钱而设计的课程来处理财务上的细微差别。
对于OP,简单的解决方案是将这些货币价值适当地舍入到整数便士。