In C and many other languages the float and double types exists, they're the primary means for decimal types, however they can sometimes vary quiet a bit. For instance if you try to divide 1 by 3, you often get a result of: 0.33333333333333331.

The reason for this result is of course the floats lack of precision, a float is normally implemented in 32-bits, just like a 32-bit integer, it has it boundaries.

To show how bad these limits can be, I wrote some sample code in C, to check if an unsigned long as a float is equal to the same number + 1.

#include <stdio.h>;
#include <limits.h>;

int main() {
  unsigned long i = 0, count = 0;
  printf("A list of bad floats from 0 to %lu:\n", ULONG_MAX);
  for (i = 0; i < ULONG_MAX; i ++) {
    if (((float) i) + 1 == (float) i) {
      // 33[E is move cursor to beginning of line.
      // 33[K is clear line from cursor and to end of line.
      printf("33[E33[K%12ld: (float) %15ld + 1 == (float) %15ld\n", ++count, i, i);
  printf("We counted %ld bad floats.\n", count);
  return 0;

The result is pretty scary, however it's rather easy to explain how this happens. Like the signed integer, a float has a signed bit at highest bit, after that comes an exponent of 8 bits, the exponent is of course binary exponentially. Last is the mantissa (or fraction), it fits the last 23 bits of the 32 bits.

Now it's funny to see that some number actually derive more than +/- 1, for instance 1/3. Now this is not entirely game breaking for most calculations, but if you take some inaccuracy through many calculations, the loss of precision will accumulate more and more.

Now, it might be unclear of how we would express decimals, however the exponent is a signed byte, so it goes from -128 to 127, if the have a negative exponent, we get a mantissa * some number between 0 and 1.

Now for the double, it's more precise, since it's 64-bits and not 32 like the float. This means we still have 1 bit for the signed bit. For the exponent we now have 11 bits and for the mantissa we have 52. This means the lack of precision is smaller, and that this lack accumulates slower.

There's of course no way to express all values accurately, as that would required unlimited memory.