Link to home
Start Free TrialLog in
Avatar of Software Software
Software SoftwareFlag for Austria

asked on

Float variable freezes after increasing

I know, that it isn't a good way to increase a float variable inside a loop. But thats not the point.
And I know that most float numbers can't exactly convert to a binary number.
Can someone explain to me detailed the behaviour on case 1 and 2?

1) Why do the counters diverge?
2) Why does the second counter freeze after some time (I get after some time the same number even though I increase floatCtr by 0.1)?

int main()
{
    uint32_t uint32Ctr=0;
    float floatCtr=0;
    for(;uint32Ctr<=100000000;uint32Ctr++){
        floatCtr+=0.1;
        if(uint32Ctr%10000==0){
            printf("uint32 Counter = %d\t float Counter = %f\n", uint32Ctr, floatCtr);
        }
    }
    return 0;
}

Open in new window

Avatar of Dave Baldwin
Dave Baldwin
Flag of United States of America image

What is the number that is displayed when it freezes?  You can reach a point where '0.1' is below the resolution of the floating point number so it is essentially 0.  Is this 32-bit or 64-bit floating point?
Avatar of dpearson
dpearson

Floating point numbers can be thought of as a value times an exponent.  If this was base 10, the value for 256 might be represented as 2.56 x 10^2.

So since floating point values in computers have limited precision, imagine a simple case where you only get 2 decimal places in the floating point value:
 e.g. 256.0 = 2.56 x 10^2

The 2 decimal places here refers to in 2.56 - there's limited precision to this expression.

But when you add 0.1 to it you get 256.1, which is still 2.56 x 10^2 - i.e. there's no difference between 256.0 and 256.1 (if floats only allowed 2 decimal places in their internal representations).  That's because they both encode to 2.56 (to 2 dp).

In other words the value would appear to freeze as you added a small number to it (0.1).

In reality, a floating point value is in binary but it's the same basic structure (a number to a certain amount of precision times an exponent).  So eventually when you add a small number to it, there's no change in the value.

I hope that makes sense.

Avatar of Software Software

ASKER

@Dave Baldwin
If you run the program, the number that is displayed when it freezes is 2097152.000000
This is a 4 Byte (32-bit) floating point.

@dpearson
I don't think that's the exact correct answer.
It has something to do that all decimal places go by the board when you slide to the right.
But I don't understand it really.
@dpearson gave you the right answer.  Floating point numbers have a limited range and precision and your experiment is exceeding the precision that is available.  This page may help.  https://www.cs.yale.edu/homes/aspnes/pinewiki/C(2f)FloatingPoint.html
It has something to do that all decimal places go by the board when you slide to the right. 
That is indeed a potential problem with decimals, but I don't think it's happening here because nothing is being shifted to the right - which is a form of division.

e.g. 2 >> 1 means "2 shifted 1 position right" which is the same as "divided by 2" (because everything is in binary).

If you divide a floating point number by a value enough times it will get very small and you'll lose precision.

But in your problem you're doing addition rather than bit shifting or division. (And bit shifting floating point values is a pretty complex subject, you'd need to really understand the details of the underlying binary representation, which isn't really necessary for your current problem).  If you'd really like to read more about it, there's lots here:
https://en.wikipedia.org/wiki/IEEE_754
but I think that's overkill for your needs (and that page makes my head hurt!)



SOLUTION
Avatar of Zoppo
Zoppo
Flag of Germany image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
...there's no n for which 2^n is a number, which can be divided by 10 without a remainder. 

Open in new window

Can someone explain this to me?
if n=1:
2^1=2 -> 2/0.1 = 20 (no remainder)


ASKER CERTIFIED SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
due to this it's just not possible to represent decimal values in binary form 

Just to clarify what Zappo is saying some decimal values can be exactly represented in binary form, while others cannot.

In general, you should not assume that all floating point values can be exactly represented which means eventually that rounding will can cause two mathematically different floating point numbers to end up with the same internal value inside a computer (which is what is happening to you here).  That's the key concept to grasp.  The details are actually quite complex, but the concept really isn't so bad.