Matok's PHP Blog

# PHP Gotcha II: When 1 plus 7 isn't 8

Look at this simple addition:

``````\$a = 0.1;
\$b = 0.7;

if (\$a + \$b == 0.8) {
echo '0.1 + 0.7 is 0.8';
} else {
echo '0.1 + 0.7 is NOT 0.8';
}
``````

The result is: 0.1 + 0.7 is NOT 0.8

Actually, this is not matter of PHP. This is how floating point arithmetic works.

## How real numbers are stored?

You can find big red warning on manual page. Important is this information:

PHP typically uses the IEEE 754 double precision format

Nice article about this topic is on wikipedia, but what about trying yourself? Here is tinny C program:

``````#include <stdio.h>
#include <stdlib.h>

void print_bits(void *a, size_t size);

int main()
{
double number;

printf("Gimme float number: ");
scanf("%lf", &number);
printf("\n");

print_bits(&number, sizeof(number));
printf("\n");

return EXIT_SUCCESS;
}

void print_bits(void *address, size_t size)
{
int i;
int b;
address += size-1;

printf("Printing %zu bytes:\n", size);
for (i = size-1; i >= 0; i--) {
for (b = 7; b >= 0; b--) {
printf("%d", (*(char *)address & (1<<b))>>b);
}

address--;
}
}
``````

You can download it from GitHub. When I enter number `0.1` on input I got this output:

0011111110111001100110011001100110011001100110011001100110011010

According to wikipedia article:

First `0` is sign and this means positive number. Next 11 bits `01111111011` is exponent. Rest of this number `001100110011001100110011001100110011001100110011010` is fraction.

Exponent `011111110112` is in decimal `1019`, but we must subtract `1023` so exponent is -4.

At the begging of fraction we put `1` and we get a number `110011001100110011001100110011001100110011001100110102` or ‭`720575940379279410` in decimal format is fraction.

Equation to concrete real number is:
2-4 * (7205759403792794 * 2-52)
2-56 * 7205759403792794

0.10000000000000000555111512312578 = `0.1`

0.69999999999999995559107901499374 = `0.7` (computed by same principles)

## Conclusion

When I add this two numbers I get 0.799999999999999961142194138119521 and that is really close to 0.8 but it isn't exactly equal. This is how real numbers are stores in computer memory no matter of programming language you are using.

If you are working with float you must consider this behavior, avoid using `==` or `===` with real numbers. You are safe if you do sum in MySQL on decimal type or use some kind of math library which can handle this float precision issue.

Footnotes:

1: All calculations were made by calculator, some last significant may be stripped - but it isn't important

If you like this article then mark it as helpful to let others know it's worth to read. Otherwise leave me a feedback/comment and we can talk about it.

I'm foreigner. Where I live my friends call me Maťok.

### Master your skills

What I know I learn from books. You can buy good literature here: Gorila - Slovak book shop