【问题标题】:Working With Floats and Integers使用浮点数和整数
【发布时间】:2012-02-11 18:30:48
【问题描述】:

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

#include <stdio.h>

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

【问题讨论】:

    标签: c floating-point integer floating-point-conversion


    【解决方案1】:
    int account = 2000;
    printf("Remaining account: %.2f\n", account);
    

    这是错误的;对于整数,它应该是 "%d",或者更好的是,将您的 account 变量类型更改为可以代表您要额外收费的 0.50 的东西。我也不建议您使用(不精确的)floats 来赚钱。当您的意思是10.5 时,您不想撤回10.499999997。您需要考虑使用的精度和舍入规则。 AFAIK 这些都是法律规定的。

    【讨论】:

      【解决方案2】:

      您根本不能使用浮点值来表示货币,因为它们具有错误的属性。并非所有数字都可以精确表示,因此您会产生“神秘”的效果。

      最好使用“定点”方法,最简单的方法是采用较大的整数类型,例如long,然后将其乘以一个整数,如果您需要的只是整美分,通常为 100(对于美国货币)。如果您需要美分的小数部分,请乘以更多,例如 10,000,以便能够表示低至 1/100:一美分的所有值。

      使用此方案,$1 将是:

      long one_dollar = 1 * 10000;
      

      13 美分将是:

      long thirteen_cents = 13 * 100;
      

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

      【讨论】:

      • 我希望通货膨胀率保持在足够低的水平,以使 64 位在我的一生中就足够了。
      【解决方案3】:

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

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

      【讨论】:

        【解决方案4】:

        让您的生活更轻松一些,与其将“整数”视为美元,不如将它们视为“美分”,这样您就不需要浮点数了。

        【讨论】:

          【解决方案5】:

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

          然而,代码中有一个更根本的缺陷。当需要精确的小数时,不应使用浮点变量来表示数字,尤其是在处理货币金额时。简而言之,在您的应用程序中不使用浮点数的原因是小数不能精确表示。在每个位置数字系统中,一些数字由无限重复的序列表示。例如,

          十进制1/3表示为0.33[3]

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

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

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

          更多详情请见What Every Computer Scientist Should Know About Floating-Point Arithmetic

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

          【讨论】:

            【解决方案6】:

            即使它是整数,您也可以将帐户打印为浮点数 (%2f),您应该改用 %d 格式说明符

            【讨论】:

              【解决方案7】:

              在处理金钱时,您可能应该使用二进制编码的十进制。它将允许您对美元和美分使用单个变量。当您使用它时,您可以指定一个 typedef struct union,它可以让您指定以美元、美分、仅整美元和仅美分为单位的值。没有与其他货币的兑换,这对几乎所有货币情况都有好处。

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2011-01-04
                • 2017-07-26
                • 2011-01-10
                • 2015-01-20
                • 2011-04-20
                • 1970-01-01
                • 2017-11-16
                • 2010-12-26
                相关资源
                最近更新 更多