-->

Working With Floats and Integers

2019-01-28 09:00发布

问题:

I've created an ATM like program which holds the money in a person's account. When the person takes out a withdrawal, it subtracts the withdrawal from the account along with a .50 surcharge. The problem I'm having is working with both integers and floats in this program. I converted the integer account to a floating point number but I get an error message when I try to print out the statement. Can someone tell me what I'm doing wrong?

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

回答1:

int account = 2000;
printf("Remaining account: %.2f\n", account);

This is wrong; it should be "%d" for integer, or better, change your account variable type to something that could represent the 0.50 you're surcharging. I don't recommend you to using (imprecise) floats for money either. You don't want to withdraw 10.499999997 when you meant 10.5. You need to think about the precision and rounding rules you'd use. AFAIK these are both mandated by laws or something.



回答2:

You simply cannot use floating-point values to represent currency, since they have the wrong properties. Not all numbers are exactly representable, so you will have "mysterious" effects.

It's better to use a "fixed-point" approach, the easiest is to take a largeish integer type such as long and then just multiplying it by an integer, typically 100 if all you need are whole cents (for US currency). If you need fractions of cents, multiply by more such as 10,000 to be able to represent all values down to 1/100:th of one cent.

With this scheme, $1 would be:

long one_dollar = 1 * 10000;

And 13 cents would be:

long thirteen_cents = 13 * 100;

Note that this in turn limits how large amounts of money you can represent. Eventually, you may find you need an arbitrary-precision library to get "unlimited"-precision integers.



回答3:

Please, do not use floats when handling money. Use an integer type, as to track cents, and then convert that at output to dollars and cents (or whatever currency).

In particular, 0.1decimal does not have an exact floating point representation. Instead, it is represented as an endless repeating binary fraction (0.19999999999....hex). Likewise, 0.01decimal is approximately 0.028F5C28F...hex.



回答4:

Make your life a little easier, and rather than thinking of your "ints" as dollars, think of them as "cents" then you won't need floating point numbers.



回答5:

The warning you see is due to the fact that you pass an int to printf() having given it %.2f as the format string. This format string is to be used for floating point numbers. See printf.

There is a more fundamental flaw in the code, however. You should not use floating point variables to represent numbers when exact decimal fractions are required, in particular when working with monetary amounts. In short, the reason not to use floating point numbers in your application is that decimal fractions cannot be represented exactly. In every positional number system some numbers are represented by an infinite repeating sequence. For example,

in decimal system 1/3 is represented as 0.33[3]

(square brackets indicating infinitely repeating sequence of digits). Similarly, in binary some numbers require infinite sequence of 0s and 1s to be represented. For example,

in binary system, 1/10 is 0.000110011[0011]

Since registers and memory locations are finite in length this is rounded up or down and represents a number slightly above or below 0.1. Thus, you cannot store the exact value 0.1 in a float or double.

For more details, see What Every Computer Scientist Should Know About Floating-Point Arithmetic.

One alternative is for example to use integer variables representing cents.



回答6:

you print account as if it was a floating point number (%2f) even though it is a integer, you should use the %d format specifier instead



回答7:

You should probably use Binary Coded Decimals when dealing with money. It will allow you to use a single variable for both dollars and cents. While you are at it, you can specify a typedef struct union that will let you specify the value in dollars, cents, whole dollars only, and cents remainder only. Short of exchange with other currencies, that will be good for just about every monetary scenario.