gbadev.org forum archive

This is a read-only mirror of the content originally found on forum.gbadev.org (now offline), salvaged from Wayback machine copies. A new forum can be found here.

C/C++ > C++ float weirdness

#29736 - _pluto9 - Wed Nov 24, 2004 4:59 pm

Last night I was making a program in MSVC 6 to convert a number into scientific notation, I wrote the part for numbers where the exponent was positive first which worked fine, then I wrote the part that handes negative exponients, for some reason, I got the following output:

(.01) = 1 x 10 ^ 2
(.001) = 10 x 10 ^ 2 <-- the error!!!
(.0001) = 1 x 10 ^ 4
(.00001) = 1 x 10 ^ 5
(.000001) = 1 x 10 ^ 6
etc..

now the code I was using looked like this (n is the original number):

Code:
for(e=-1, d=10.0f; abs(n)*d <= 0.1f; e--, d*=10.0f);


I isolated the error, and found that it wasn't getting the third loop (where d would be 1000.0f, and e would be -3), because (0.001 * 100.0f) <= 0.1 was returning false .... ?!@#!@$!

I could figure for the life of me, why it was doing that, so I changed all my floats to doubles, and the problem disapeared.

Is this an issue with floats in general? or is it a bug in MSVC 6?

#29738 - poslundc - Wed Nov 24, 2004 5:12 pm

It is not possible to perfectly represent the number 0.1 (and likewise 0.01, 0.001, etc.) in base-2. It is a repeating fraction, like 1/3 is when represented in base-10 (which evaluates to 0.3333...). Programs that repeatedly add or subtract numbers like 0.1 will usually accumulate a noticeable error.

There are more sophisticated math libraries available if you require more scientific accuracy, but the general rule for computational programming is to remember that you are always working with discrete values. If you need to check for equality with floats, you ought to define a function to do so (or overload the "==" operator) that checks if the two values are within a certain tolerance.

Dan.

#29748 - _pluto9 - Wed Nov 24, 2004 6:40 pm

I kinda understand that..

but in my code I wasn't doing any adding or subtracting of floats... just multiplying and dividing, so I'm guessing this goes for multiplying and dividing as well?

now if I did this all using fixed point math, would it illiminate these problems?

#29753 - poslundc - Wed Nov 24, 2004 7:08 pm

_pluto9 wrote:
I kinda understand that..

but in my code I wasn't doing any adding or subtracting of floats... just multiplying and dividing, so I'm guessing this goes for multiplying and dividing as well?


You get the most noticeable error from accumulation, but multiplication and division always introduce error as well.

Exercise: run the following program on your computer and see why your conditional of (0.001 * 100.0f) <= 0.1 doesn't hold:

Code:
int main(void)
{
    float a = 100;
    float b = 0.001;
   
    printf("%.20f\n", 0.1);
    printf("%.20f\n", (a * b));

    return 0;
}


Quote:
now if I did this all using fixed point math, would it illiminate these problems?


No, but it would possibly make you much more aware of both where and why these problems are occurring in your code.

I generally wouldn't recommend bothering with fixed-point if you're writing your program for a computer with an FPU. If you're writing it for the GBA, on the other hand, you should probably use exclusively fixed-point.

Dan.