我有这个函数用于返还金钱阵列中的钱。但它不需要0.01。我知道这是因为0.01不能精确地以二进制代码传输。但我只想要折扣0.01。我也有行printf("%.2f",money[15]);
显示钱[15]是0.00而不是我想要0.01。
void returning(float toReturn) {
float money[15] = {500.00,200.00,100.00,50.00,20.00,10.00,5.00,2.00,1.00,0.5,0.2,0.1,0.05,0.02,0.01};
int i;
printf("%.2f",money[15]);
printf("Pick your change: ");
while (toReturn >= 0){
for (i = 0; i < 15; i++) {
if (toReturn >= money[i]) {
toReturn -= money[i];
printf("Return: %.2f\n",money[i]);
break;
}
}
}
}
谢谢:)
答案 0 :(得分:3)
0.01没有精确准确的浮点表示。
正如其他人告诉你的那样,这里正确的答案是不使用浮点数。通过从美元切换到美分来使用“固定点”(仅当您准备好向用户显示结果时重新格式化),这将通过避免舍入问题为您提供更好的准确性。或者使用二进制计数十进制系统,例如Java的BigInteger类,它将具有舍入问题但至少会以对人类更自然的方式进行舍入(它将难以准确地表示1/3而不是1 /例如,10)。
答案 1 :(得分:0)
问题1:阵列:“钱[15]是0.00而不是我想要的0.01。”这显然是错误的。 money[15]
超出了合法指数0,1,2,3,...... 14。在这一点上,代码可能很简单。
float money[15] = {500.00,200.00, ... 0.02,0.01};
printf("%.2f",money[15]);
问题2:启用了警告的现代编译器至少会给printf("%.2f",money[15]);
诊断启用所有警告或获取新编译器。
问题3:误解如何使用浮点数来表示离散的派系值,如美元和美分:
使用if (toReturn >= money[i]) {
很容易失败,因为比较中没有容差。假设代码工作到分(0.01),那么比较可能是(RoundToNearestCent(toReturn) >= RoundToNearestCent(money[i]))
。但是四舍五入到最接近的0.01是昂贵的,并且还有其他微妙的问题。因此,建议计算一切美分。然后可以使用round()
,roundf()
快速完成舍入到最接近的整数。
范围:典型float
可以精确地代表美分到大约$ -160,000.00到$ + 160,000.00的范围。这可能适用于有限的用途,但double
的确切分数范围是美国国债的10倍。
知道何时轮流:每次计算后,财务代码都可以转到一分钱,但编写良好的代码将更加务实。
double a,b,c;
a = 123456.0; // $1,234.56
b = 1.0; // 1 cent
c = a - b; // rounding not needed, inputs are whole numbers, in range & subtraction is exact.
a = 123456.0; // $1,234.56
b = 3.7; // 3.7% interest
c = round(a*b/100); // rounding needed as product is not exact
某些平台提供十进制编码的浮点数,这非常有帮助。但知道何时进行回合仍然很重要。