The Unpredictability of float data type : Explained

The Unpredictability of float data type : Explained

Ever wondered why one of the C data types is called float ?Because in some cases it literally floats nearby expected values.For example :-when you do multiple operations between two relatively small and large values of float.

Proof

int main(){

float x=0.001f;

for(i=0;i<=40000;i++){

x=0.0001f+ x;

printf(“%f\n”,x);}}

So add 0.0001 to 0.001 and keep adding and printing it

O/P:-

0.001100

0.001200 (OK so far)

.

0.063400

0.063501 (where did 1 come from?)

.

0.122501

0.122602 (2??)

.

0.390185

0.390285

Woa X where are you going ?Why?

Before answering the why we need to understand what is float?How it works?How is it stored?

What is Float?

According to IEEE754 Float is a 4-bytes data type stored in 3 parts:-1)Sign 2)Mantissa 3)Exponent

i.e float = 2^(exp) x 1.(mantissa bits in binary)

Simple?Not so much !!!!!

Think about this.

For saving a float we have 4 bytes distributed as below

s e e e e e e e e m m m m m m m m m m m m m m m m m m m m m m m

31                                                                                                                                 0

1 Sign is simple +ve / -ve

2 Exponent is binary number from which we subtract 127 to get exp and than 2^exp

3 Mantissa

This one is tricky.Basically if you have a number in binary form for example 1101.000101 you give 1.101000101 as Mantissa where 1 is always supposed to be there (for valid non zero floating point value) and thus not needed to be mentioned and you add 3 in exponent to get proper value.

Just like saying in decimal that 100 is 1.0 * (10^2) to shift decimal point

Now if we want to add two numbers which are comparatively very big / small to each other we mess things up!!!!

if we want to add 0.00000001 to 1.0 we get 1.0 !!!!

There is a lot more going on in how addition , multiplication etc is done behind the scenes in background but in short float is not precise in certain situations.

Reason : The exponent itself (i.e the scaling)

Each float consists of exponent which determines how large / small a number is.

This means we can either represent very large / very small numbers.

Adding two floats whose scale difference is very big will sometimes result in the smaller one vanishing as we can not represent that small of a value into the larger scale.

Let’s see it like this

Simple Explanation!

Suppose we use a similar data type in decimal form and we can save only 12 digits in mantissa including before and after the decimal point

Take two decimals 100.0000000100 and 1.000000000011 and add them

that means 1.000000000100 * 10^2 +1.000000001100 * 10^0

9876543210                          9876543210

so result is 101.000000010011 to be saved as 1.01000000010011 * 10^2

9876543210

BUT We can save only 12 digits after 1st 1!!! We have to discard the last 2 digits (11) to fit it in 12 digits.

We added 2 12 digit numbers but we have to discard precision of smaller number due to difference
in exponent!
In short the precision / range of numbers in right side reduces as left side numbers get bigger!
That is how it is and that is how it fits into just 4 bytes which is good.
Next time you use float make sure you know how it gets stored in memory and how it can give unexplainable results in some scenarios.

Advertisements