Странное поведение при сравнении double, два PHP-двойных значения не эквивалентны - PullRequest
5 голосов
/ 11 марта 2011

У меня есть два, казалось бы, одинаковых двойных значения в PHP (по крайней мере, при их отображении).

Но при сравнении их с двойными равными по какой-то причине он оценивается как ложный.Есть ли какие-то особые соображения при выполнении такого сравнения?

Ответы [ 4 ]

9 голосов
/ 11 марта 2011

Вы не должны сравнивать числа с плавающей запятой, используя оператор ==.

См. Большое предупреждение и explanation in the php manual

Что сработает, так это утверждениедва числа находятся на некотором небольшом расстоянии друг от друга, как это:

if(abs($a - $b) < 0.0001) {
    print("a is mostly equal to b");
}

Причина в том, что ошибки округления из-за арифметики с плавающей запятой выполняются после того, как десятичные числа преобразованы в двоичные, а затем преобразованы обратно в десятичные,Эти обратные преобразования вызывают явление, когда 0.1 + 0.2 не равно 0.3.

1 голос
/ 05 апреля 2018

Небольшая функция, которую я сделал, надеюсь, кому-то поможет:

function are_doubles_equal($double_1, $double_2, $decimal_count) {
    if (!$decimal_count || $decimal_count < 0) {
        return intval($double_1) == intval($double_2);
    }
    else {
        $num_1 = (string) number_format($double_1, $decimal_count);
        $num_2 = (string) number_format($double_2, $decimal_count);
        return $num_1 == $num_2;
    }
}

Использование:

$a = 2.2;
$b = 0.3 + 1.9002;

are_doubles_equal($a, $b, 1); // true : 2.2 == 2.2 
are_doubles_equal($a, $b, 1); // false : 2.2000 == 2.2002
1 голос
/ 11 марта 2011

Представление чисел с плавающей запятой в PHP (, а также в C и многих других языках ) неточно.Из-за этого, казалось бы, одинаковые числа на самом деле могут быть разными, и сравнение не удастся.Вместо этого выберите небольшое число и убедитесь, что разница меньше этой, например:

if(abs($a-$b)<0.00001) {
  echo "Equal!";
}

См. Также объяснения в руководстве по PHP .

1 голос
/ 11 марта 2011

float и double никогда не должны сравниваться на равенство: есть ошибки точности, которые делают два числа различными, даже если они кажутся равными (когда они распечатаны, они обычно округляются).

Правильный способ сравнения - использование некоторой константы DELTA:

define(DELTA, 0.00001); // Or whatever precision you require

if (abs($a-$b) < DELTA) {
  // ...
}

Также обратите внимание, что это не специфично для PHP, но важно и для других языков (Java, C, ...)

...