Despite this issue having been addressed countless times until now, a variant of this age-old question still pops up on StackOverflow on a weekly basis (at least), and since I’ve bumped by own head into it before, I figured writing this down one more time couldn’t hurt, right?
The in-depth explanation for why programming languages cannot properly handle floating point precision has been too well-documented before for me to repeat it here. I strongly suggest reading What Every Computer Scientist Should Know About Floating-Point Arithmetic, but if you don’t have the time or inclination, here is a small quote from the PHP documentation on floating point precision:
[…] rational numbers that are exactly representable as floating point numbers in base 10, like 0.1 or 0.7, do not have an exact representation as floating point numbers in base 2, which is used internally, no matter the size of the mantissa. Hence, they cannot be converted into their internal binary counterparts without a small loss of precision. This can lead to confusing results: for example, floor((0.1+0.7)*10) will usually return 7 instead of the expected 8, since the internal representation will be something like 7.9999999999999991118…
So never trust floating number results to the last digit, and do not compare floating point numbers directly for equality.
The warning at the end of the quote is, of course, doubly important when you deal with numbers that represent money and prices.
Thankfully, PHP provides a set of math functions to handle arbitrary precision operations and comparisons. The example at the top of the page would therefore become:
bccomp(bcadd(0.1, 0.7, 1), 0.8, 1) === 0;
A lot wordier, I know, and more difficult to read, but guaranteed to provide precise results that you can count on.