Как узнать, равны ли два float в PHP
6 декабря 2019
Тип float не отличается точностью, страдают от ошибок округления и сравнивать как обычно их нельзя. Почему так отлично написано на специальном сайте floating-point-gui.de.
В PHP узнать, равны ли два float и не нарваться на ошибки можно так:
$equal = \abs($a - $b) < PHP_FLOAT_EPSILON;
PHP_FLOAT_EPSILON
— машинный ноль для PHP.
Для PHP < 7.2 можно в качестве epsilon использовать 0.0001.
Комментарии RSS по email OK
Это во всех нормальных языках так. В ещё более нормальных есть ф-я, которая заменяет вызов abs и сравнение с эпсилон.
Конечно, такое сравнение не означает, что два флоата равны. Они равны с некой точностью.
Или юзать bcmath и не страдать костылями...
Я когда-то хранил деньги в MySQL в типе float, но случилось страшное и с тех пор храню в INT и только копейки :)
Лишняя скобка в конце выражения.
+1 за использование bccomp.
Сомнительный совет, если честно. Если считать что-то сложнее, чем 1/3*3, результат сильно удивит: дело в том, что погрешность при вычислениях накапливается.
sin x == sin(x + 2πn), n∈Z
arcsin(sin x) == arcsin(sin(x + 2πn))
|x-arcsin(sin x)| < PHP_FLOAT_EPSILON
а
|x-arcsin(sin(2π+x))|> PHP_FLOAT_EPSILON
:-)
var_dump(abs(pi()/4 - asin(sin(2*pi() + pi()/4))) < PHP_FLOAT_EPSILON);
в PHP 7.2 даст false
PS: ну и сравнивая числа с плавающей точкой, нужно понимать, как оно всё внутри устроено. Потому что для
var_dump(1.0 === 1.0 + PHP_FLOAT_EPSILON/2); var_dump(0.5 === 0.5 + PHP_FLOAT_EPSILON/2); var_dump(0.25 === 0.25 + PHP_FLOAT_EPSILON/4);
результат будет true, false, false
Для этого DECIMAL существует.
Я знаю, но в копейках оказалось удобнее всего
вот только прям на главной стоит предостережение - что сравниваются именно строки. И float будет сначала сконвертирован в строку, а уже потом будет происходить сравнение. Пруф: www.php.net/manual/ru/intro.bc.php
Я когда-то хранил деньги в MySQL в типе INT в виде значения, полученного умножением искомого значения на 100... В том числе суммы не только в рублях, а и в других валютах тоже, в числе которых были валюты, где значения всегда целые... Но потом выяснилось, что существуют валюты, в которых после запятой может быть до 3 знаков... А еще, оказывается, есть криптовалюты, где после запятой может быть до 18 знаков... В общем, с некоторых пор храню деньги в DECIMAL. :)) А арифметические операции выполняю с использованием bcmath. Чего и всем рекомендую. :)))