使用浮点数和整数

我已经创建了一个ATM程序,它将钱存入一个人的账户。 当该人取出提款时,它会从账户中扣除50%的附加费。 我遇到的问题是在这个程序中使用整数和浮点数。 我将整数帐户转换为浮点数,但是当我尝试打印语句时收到错误消息。 有人能告诉我我做错了什么吗?

#include  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; } 

 int account = 2000; printf("Remaining account: %.2f\n", account); 

这是错的; 对于整数,它应该是"%d" ,或者更好,将您的account变量类型更改为可能代表您正在充电的0.50。 我不建议你使用(不精确) float钱。 当你的意思是10.5时,你不想撤销10.499999997 。 您需要考虑您使用的精度和舍入规则。 AFAIK这些都是法律规定的。

您根本无法使用浮点值来表示货币,因为它们具有错误的属性。 并非所有数字都可以完全表示,因此您将拥有“神秘”效果。

最好使用“定点”方法,最简单的方法是采用一个很大的整数类型,例如long ,然后将它乘以一个整数,如果你需要的只是整数美分(美元),通常为100。 如果你需要分数的分数,乘以更多,如10,000,以便能够代表所有值低至1/100:百分之一。

有了这个计划,$ 1将是:

 long one_dollar = 1 * 10000; 

13美分将是:

 long thirteen_cents = 13 * 100; 

请注意,这反过来限制了您可以代表的大笔金额。 最终,您可能会发现需要一个任意精度的库来获得“无限制”的精度整数。

在处理钱时不要使用花车。 使用整数类型,以跟踪美分,然后将输出转换为美元和美分(或任何货币)。

特别是,0.1 十进制没有精确的浮点表示。 相反,它表示为无穷无尽的重复二进制分数(0.19999999999 …… hex )。 同样,0.01 十进制约为0.028F5C28F … hex

让你的生活变得更轻松,而不是把你的“in”想象为美元,把它们想象成“美分”,那么你就不需要浮点数了。

您看到的警告是由于您将一个int传递给printf() ,并将%.2f 。。 %.2f作为格式字符串。 此格式字符串用于浮点数。 见printf 。

但是,代码中存在更为根本的缺陷。 当需要精确的小数部分时,不应使用浮点变量来表示数字,特别是在使用货币金额时。 简而言之,在您的应用程序中不使用浮点数的原因是小数分数无法准确表示。 在每个位置编号系统中,一些数字由无限重复序列表示。 例如,

在十进制系统1/3中表示为0.33 [3]

(方括号表示无限重复的数字序列)。 类似地,在二进制中,一些数字需要表示0和1的无限序列。 例如,

在二进制系统中,1/10是0.000110011 [0011]。

由于寄存器和存储器位置的长度是有限的,因此向上或向下取整并表示略高于或低于0.1的数字。 因此,您不能将精确值0.1存储在floatdouble

有关更多详细信息,请参阅每个计算机科学家应该知道的关于浮点运算的内容 。

一种替代方案是例如使用表示美分的整数变量。

你打印帐户好像它是一个浮点数( %2f ),即使它是一个整数,你应该使用%d格式说明符代替

你应该在处理钱时使用二进制编码小数。 它允许您使用单个变量来计算美元和美分。 在您使用它时,您可以指定一个typedef结构联合,它允许您以美元,分,仅美元和仅剩余分数来指定值。 与其他货币交易不足,这对几乎每种货币情况都有好处。