我创建了一个ATM程序,它将钱存入一个人的账户。当该人取出提款时,它会从账户中扣除50%的附加费。我遇到的问题是在这个程序中使用整数和浮点数。我将整数帐户转换为浮点数,但是当我尝试打印语句时收到错误消息。有人能告诉我我做错了吗?
#include <stdio.h>
int main (void) {
int account = 2000;
int withdrawal;
float charge = 0.50;
printf ("How much money would you like to take out? ");
scanf ("%i", &withdrawal);
while (withdrawal % 5 != 0) {
printf ("Withdrawal must be divisible by 5. ");
scanf("%i", &withdrawal);
}
account = ((float) account - charge) - withdrawal;
printf("Remaining account: %.2f\n", account);
return 0;
}
答案 0 :(得分:7)
int account = 2000;
printf("Remaining account: %.2f\n", account);
这是错的;对于整数,它应该是"%d"
,或者更好,将account
变量类型更改为可能代表您正在充电的0.50的变量。我建议您不要使用(不精确)float
s。当您的意思是10.499999997
时,您不想撤销10.5
。您需要考虑您使用的精度和舍入规则。 AFAIK这些都是法律规定的。
答案 1 :(得分:5)
您根本无法使用浮点值来表示货币,因为它们具有错误的属性。并非所有数字都是完全可表示的,因此您将产生“神秘”效果。
最好使用“定点”方法,最简单的方法是采用一个大的整数类型,例如long
,然后将它乘以一个整数,如果你需要的只是整数,通常为100(对于美国货币)。如果你需要分数的分数,乘以更多,如10,000,以便能够代表所有值低至1/100:百分之一。
使用此方案,$ 1将是:
long one_dollar = 1 * 10000;
13美分将是:
long thirteen_cents = 13 * 100;
请注意,这又会限制您可以代表的金额。最终,您可能会发现需要一个任意精度的库来获得“无限制”的精度整数。
答案 2 :(得分:3)
请,处理钱时不要使用花车。使用整数类型,以跟踪美分,然后将输出转换为美元和美分(或任何货币)。
特别是,0.1 decimal 没有精确的浮点表示。相反,它表示为无穷无尽的重复二进制分数(0.19999999999 .... hex )。同样,0.01 decimal 约为0.028F5C28F ... hex 。
答案 3 :(得分:1)
让你的生活变得更轻松,而不是把你的“in”视为美元,把它们想象成“美分”,那么你就不需要浮点数了。
答案 4 :(得分:1)
您看到的警告是由于您将int
传递给printf()
并将%.2f
作为格式字符串。此格式字符串用于浮点数。请参阅printf。
然而,代码中存在更为根本的缺陷。当需要精确的小数部分时,不应使用浮点变量来表示数字,特别是在使用货币金额时。简而言之,在您的应用程序中不使用浮点数的原因是小数分数无法准确表示。在每个位置编号系统中,一些数字由无限重复序列表示。例如,
小数系统1/3中的表示为0.33 [3]
(方括号表示无限重复的数字序列)。类似地,在二进制中,一些数字需要表示0和1的无限序列。例如,
在二元系统中,1/10是0.000110011
由于寄存器和存储器位置的长度是有限的,因此向上或向下取整并表示略高于或低于0.1的数字。因此,您无法将精确值0.1存储在float
或double
。
有关详细信息,请参阅What Every Computer Scientist Should Know About Floating-Point Arithmetic。
一种替代方法是使用表示分数的整数变量。
答案 5 :(得分:0)
您打印帐户就好像它是一个浮点数(%2f
),即使它是一个整数,您应该使用%d
格式说明符
答案 6 :(得分:0)
在处理金钱时,您应该使用二进制编码的小数。它允许您使用单个变量来计算美元和美分。在您使用它时,您可以指定一个typedef结构联合,它允许您以美元,美分,仅美元和仅剩余分数来指定值。与其他货币交易不足,这对几乎每种货币情况都有好处。