Если кто-то все еще посещает эту страницу с подобными проблемами, где вычитание с плавающей точкой вызывает ошибку или странные значения.Я хочу объяснить эту проблему немного подробнее.Виновником является числа с плавающей запятой.Чтобы проиллюстрировать проблему, я объясню, почему на простом примере, и вы можете предположить, почему это влияет на округление и т. Д.
Это не имеет прямого отношения к PHP и не является ошибкой.Однако каждый программист должен знать об этой проблеме.
Эта проблема унесла много жизней два десятилетия назад.
25 февраля 1991 г. эта проблема при вычислении плавающего числа в ракетной батарее MIM-104 Patriot не позволила перехватить поступающую ракету "Скад" в Дахране, Саудовская Аравия, что привело к гибели 28 солдат из 14-го квартирмейстера армии СШАОтрыв.
Но почему это происходит?
Причина в том, что значения с плавающей запятой представляют ограниченную точность.Таким образом, значение может не иметь одинакового строкового представления после какой-либо обработки.Он также включает в себя запись значения с плавающей запятой в ваш скрипт и его непосредственную печать без каких-либо математических операций.
Простой пример:
$a = '36';
$b = '-35.99';
echo ($a + $b);
Вы ожидаете, что он напечатает 0,01, верно?Но он напечатает очень странный ответ, такой как 0,009999999999998
Как и другие числа, числа с плавающей запятой double или float сохраняются в памяти в виде строки 0 и 1.Отличие числа с плавающей точкой от целого состоит в том, как мы интерпретируем 0 и 1, когда хотим посмотреть на них.Есть много стандартов, как они хранятся.
Числа с плавающей запятой обычно упаковываются в компьютерные данные в виде знакового бита, поля экспоненты и значимого или мантиссы слева направо ....
Десятичные числа не являютсяхорошо представлен в двоичном коде из-за нехватки места.Итак, вы не можете выразить 1/3 точно так же, как это 0,3333333 ..., верно?Почему мы не можем представить 0.01 как двоичное число с плавающей точкой по той же причине.1/100 - это 0,00000010100011110101110000 ..... с повторением 10100011110101110000.
Если 0,01 хранится в упрощенном виде и усеченной системой в 01000111101011100001010 в двоичном формате, то при переводе обратно в десятичное число будет выглядеть0,0099999 .... в зависимости от системы (64-битные компьютеры обеспечат вам гораздо более высокую точность, чем 32-битные).В этом случае операционная система решает, печатать ли ее, как она видит, или сделать ее более понятной для человека.Таким образом, это зависит от машины, как они хотят представить это.Но это может быть защищено на уровне языка различными способами.
Если вы отформатируете результат, введите echo number_format (0.009999999999998, 2);он напечатает 0,01.
Это потому, что в этом случае вы указываете, как следует читать и какую точность вам требуется.Ссылки: 1 , 2 , 3 , 4 , 5