-2

So I have this program in which I need to compare values in 0.0X range and if I scan for example 50.21 with this little thing

scanf("%f",bill);

the value stored in var. bill is actually 50.2099990845... which messes up calculations later in program. Is there any way to turn this number into 50.210000? Thanks for your time.

Erik
  • 15
  • 1
  • 6
  • 1
    No, for the usual reason. 50.21 is not exactly representable. Maybe you can use fixed point arithmetic? – harold Apr 09 '16 at 20:39
  • 1
    I assume you meant `scanf("%f",&bill);`, with the address-of operator? Or is `bill` a pointer? – Some programmer dude Apr 09 '16 at 20:40
  • 2
    You know how `1/3` represented as decimal with a point is `0.333...` going on forever? Well, `1/10` represented as binary with a point does the same thing - as does `1/100`. This is a problem when converting values represented as exact decimals into binary floating point - there are special cases where it works (whole numbers, multiples of 0.5, or 0.25, or 0.125 etc etc) but in general, it can't be done, you have to accept the nearest approximation that fits in whichever binary floating point representation is being used. –  Apr 09 '16 at 20:56

2 Answers2

0

Don't use IEEE-754 floating numbers (single, float, double) for decimal calculations where all digits are equally significant (as far as business-rules are concerned). This is because IEEE-754 has rounding errors and cannot represent some trivial decimal numbers accurately. It's really meant for scientific and engineering applications where small amounts of information-loss are acceptable.

If you're dealing with fixed-precision decimal numbers (such as currency values) the best approach is to use premultiplied integers, so 100 (for 100 cents) represents 1 dollar.

If you're going to use scanf, I recommend this:

int dollars = 0, cents = 0;
bool done = false;
while( !done ) {
    done = scanf("%4d.%2d", &dollars, &cents) != 2
}

cents += dollars * 100;

Note my use of the maximum-length specifiers (4 and 2 respectively) to prevent a buffer-overrun in scanf.

Dai
  • 141,631
  • 28
  • 261
  • 374
0

Floats in C (and most other languages) are stored as IEEE-754 representations. You can think of these as base-two approximations of numbers in scientific notation.

In your case, 50.21 cannot be represented exactly in binary because .21 is not a multiple of 2, so the software does its best by rounding to 50.2099990845.

For financial applications, you're better off storing an integer with the amount in cents, not dollars (or equivalent). This way, you won't end up with any rounding errors along the way!

LS97
  • 336
  • 4
  • 15