0.1 is not 0.1. Yups!

Computers can’t store 0.1 accurately. It is stored as 0.1000000015! In this post we explore and take a look at what is really going on.

Don’t trust me? Dont have to. Compile and run the following C code

#include <stdio.h>

void main() {
  float value = 0.1;

  printf("value: %0.10f\n", value);
}

Assuming the code above is saved in main.c, you can compile and run the compiled code as shown below -

~/
❯ gcc main.c

~/
❯ ./a.out
0.1000000015

Computers don’t store 0.1 as 0.1? That is correct!

How is 0.1 represented?

Try another experiment. Compile and run the following -

#include <stdio.h>

void main() {
  float value = 0.1;

  printf("value: %0.10f\n", value);
  printf("In Hex: 0x%x\n", *(unsigned int *)&value);
}

I see the following output.

~/
❯ gcc main.c

~/
❯ ./a.out
value: 0.1000000015
In Hex: 0x3dcccccd

Say hello to - IEEE 754 floating-point format :)

A floating-point number is typically represented using the IEEE 754 standard for single-precision floating-point format. This format uses 32 bits (or 4 bytes) of memory to represent a floating-point number.

The single-precision floating-point format consists of three parts: the sign bit, the exponent, and the mantissa (also known as the significand).

The exponent is an 8-bit field that represents the magnitude of the number. It is biased by 127, which means that an exponent of 0 represents a very small number (close to zero), while an exponent of 255 represents a very large number (such as infinity).

The mantissa is a 23-bit field that represents the significant digits of the number. It includes the fractional part of the number and is used to store the precision of the number.

❗ Notice that the fractional part is xxx.. in 1.xxx... and that, every number is reduced to 1.something and the exponent is adjust accordingly.

Back to 0x3dcccccd

32-bit representation of the number 0.1 using the single-precision floating-point format: 0x3dcccccd(hex) which in binary translates to -

0 01111011 10011001100110011001101

Breaking this down, we can see that:

  • The sign bit is 0, which means that the first bit is 0.
  • The exponent is 01111011, which represents 123 in decimal. Adding the bias of 127 gives us an exponent of -4.
  • The mantissa is 10011001100110011001101. To convert this to decimal, we can interpret it as a binary fraction by placing a binary point at the left end and multiplying each bit by the corresponding power of two:
0 01111011 10011001100110011001101
= 1.10011001100110011001101(binary) x 2^-4
= 1.60000002384(decimal) x 2^-4
= 0.1000000015(decimal)

Try

There are many more decimal numbers that cannot be represented accurately. Can you guess some?