我有这个函数可以在钱数组中返回钱。但不需要0.01。我知道这是因为0.01不能精确地以二进制代码传输。但我只想让它折扣0.01。我也有行
printf("%.2f",money[15]);
显示 than Money[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.01 没有精确的浮点表示。
正如其他人告诉您的那样,正确的答案是不使用浮点。通过从美元切换到美分来使用“定点”(仅当您准备好向用户显示结果时才重新格式化),这将通过避免舍入问题来为您提供更高的准确性。或者使用二进制计数十进制系统,例如 Java 的 BigInteger 类,它会存在舍入问题,但至少会以对人类更自然的方式进行舍入(它在准确表示 1/3 而不是 1/ 时会遇到困难)例如 10)。
问题 1:数组:“money[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]); // Bad
问题 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
一些平台提供十进制编码的浮点数,这非常有帮助。 但知道何时轮换仍然很重要。