Не точность float в PHP

Знал что тип float не точен, но первый раз столкнулся с этим недавно. Рассмотрим пример:

<?php
$var1 = 0.3;
$var2 = 0.2 + 0.1;

var_dump($var1 === $var2); // bool(false)

Так происходит потому, что числа с плавающей точкой имеют ограниченную точность. Следующий пример показывает наглядно:

<?php
$var1 = 0.3;
$var2 = 0.2 + 0.1;

echo number_format($var1, 20); // 0.29999999999999998890
echo number_format($var2, 20); // 0.30000000000000004441

После арифметических операций можно округлить результат, но я все равно не рекомендую проверять равенство у типа float:

<?php
$var1 = 0.3;
$var2 = round(0.2 + 0.1, 1);

echo number_format($var1, 20); // 0.29999999999999998890
echo number_format($var2, 20); // 0.29999999999999998890

var_dump($var1 === $var2); // bool(true)

Для сравнения чисел с плавающей точкой в PHP лучше использовать функцию bccomp.

Функция bccomp

bccomp(string $left_operand, string $right_operand [, int $scale = 0 ]): int

Параметры

  • $left_operand — левый операнд в виде строки
  • $right_operand — правый операнд в виде строки
  • $scale — необязательный аргумент scale задает количество цифр после десятичной точки, которое будет участвовать в сравнении

Возвращаемые значения

  • 0 — значения $left_operand и $right_operand равны
  • 1 — значение $left_operand больше чем $right_operand
  • -1 — значение $left_operand меньше чем $right_operand

Пример:

<?php
$var1 = 0.3;
$var2 = 0.2 + 0.1;

var_dump(bccomp($var1, $var2, 1)); // int(0)