我正在尝试在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(在某些情况下) .
例如 .
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,我仍然会遇到相同类型的截断错误,特别是在以下场景中:
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 回答
Round 到整数 .
考虑
payment, price, change
中的值:10.69,10.00,0.69 .典型的
double
可以精确地表示大约2 ** 64个不同的数字 . 由于大多数double
使用二进制表示,因此数字的精确十进制值(如1.23)不在该集合中 . 在这种情况下,cin>>price
会将文本转换为最接近的double
.下面发生密钥失败 . 让我们假设
change - dollars * 100
导致68.99999999999998578914528479799628257751465
. 转换为int coins
的值是68
而不是希望69
. 该值未舍入到最近,但截断为零 .处理这个问题的方法很多,都有利有弊 .
以类似
long long
的整数货币开头,就像一分钱一样基本单位而言 . (con:溢出问题,基本单位的一小部分货币 Value ,利率/利率计算等)使用十进制浮点类型 . (通常不可用或仿真速度慢)
使用定点类型 . (更少可用)
使用专门为金钱设计的课程,其中包含上述其中一项以处理财务细微差别 .
对于OP,简单的解决方案是将这些货币 Value 适当地舍入到整数便士 .
永远,永远,永远,永远,永远不会因任何原因用任何编程语言记录具有浮点值的货币值 .
如果您的代码与加油站价格一起使用时感谢我,并在需要以文本方式显示它们时将它们乘以美元金额 . 编写一个自定义
Currency
类,它将自动执行这些转换,并将金额的内部记录保持为一个整数定点数,但它将转换为浮点数,仅在需要时显示 .要添加Xirema的答案,如果您需要编写货币类时可能会考虑的事项示例,可以使用code review上的帖子作为参考 .
我可能会把这个特定的问题砍掉
change - dollars * 100
,默认情况下整数转换不会舍入 .@xirema是对的,错误主要在这一行
虽然它的合法性,并且变化= 69和美元= 0,但之后硬币将是68 .
不要这样做,最好使用int .
如果你现在要解决这个问题,这是做坏事的坏方法 .