使0.01浮动工作

时间:2014-03-10 19:00:49

标签: c floating-point

我有这个函数用于返还金钱阵列中的钱。但它不需要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;
                }
            }
        } 
    }

谢谢:)

2 个答案:

答案 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

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