让 0.01 浮点数发挥作用

问题描述 投票:0回答:2

我有这个函数可以在钱数组中返回钱。但不需要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;
                }
            }
        } 
    }

谢谢你:)

c floating-point
2个回答
3
投票

0.01 没有精确的浮点表示。

正如其他人告诉您的那样,正确的答案是不使用浮点。通过从美元切换到美分来使用“定点”(仅当您准备好向用户显示结果时才重新格式化),这将通过避免舍入问题来为您提供更高的准确性。或者使用二进制计数十进制系统,例如 Java 的 BigInteger 类,它会存在舍入问题,但至少会以对人类更自然的方式进行舍入(它在准确表示 1/3 而不是 1/ 时会遇到困难)例如 10)。


1
投票

问题 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

一些平台提供十进制编码的浮点数,这非常有帮助。 但知道何时轮换仍然很重要。

© www.soinside.com 2019 - 2024. All rights reserved.