Числа с плавающей запятой

Числа с плавающей запятой (также известные как "float", "double" или "real") могут быть определены следующими синтаксисами:

<?php
$a 
1.234
$b 1.2e3
$c 7E-10;
$d 1_234.567// начиная с PHP 7.4.0
?>

Формально, начиная с PHP 7.4.0 (ранее подчеркивание не разрешалось):

LNUM          [0-9]+(_[0-9]+)*
DNUM          ([0-9]*(_[0-9]+)*[\.]{LNUM}) | ({LNUM}[\.][0-9]*(_[0-9]+)*)
EXPONENT_DNUM (({LNUM} | {DNUM}) [eE][+-]? {LNUM})

Размер числа с плавающей запятой зависит от платформы, хотя максимум, как правило, составляет 1.8e308 с точностью около 14 десятичных цифр (64-битный формат IEEE).

Внимание

Точность чисел с плавающей запятой

Числа с плавающей запятой имеют ограниченную точность. Хотя это зависит от операционной системы, в PHP обычно используется формат двойной точности IEEE 754, дающий максимальную относительную ошибку округления порядка 1.11e-16. Неэлементарные арифметические операции могут давать большие ошибки, и, разумеется, необходимо принимать во внимание распространение ошибок при совместном использовании нескольких операций.

Кроме того, рациональные числа, которые могут быть точно представлены в виде чисел с плавающей запятой с основанием 10, например, 0.1 или 0.7, не имеют точного внутреннего представления в качестве чисел с плавающей запятой с основанием 2, вне зависимости от размера мантиссы. Поэтому они и не могут быть преобразованы в их внутреннюю двоичную форму без небольшой потери точности. Это может привести к неожиданным результатам: например, floor((0.1+0.7)*10) скорее всего вернет 7 вместо ожидаемого 8, так как результат внутреннего представления будет чем-то вроде 7.9999999999999991118....

Так что никогда не доверяйте точности чисел с плавающей запятой до последней цифры и не проверяйте напрямую их равенство. Если вам действительно необходима высокая точность, используйте математические функции произвольной точности и gmp-функции.

"Простое" объяснение можно найти в » руководстве по числам с плавающей запятой, которое также называется "Why don’t my numbers add up?" ("Почему мои числа не складываются?")

Преобразование в число с плавающей запятой

Из строк

Если строка содержащая число или ведущая числовая, тогда она будет преобразована в соответствующее целочисленное значение, в противном случае она преобразуется в ноль (0).

Из других типов

Для значений других типов преобразование выполняется путем преобразования значения сначала в целое число (int), а затем в число с плавающей запятой ( float ). Смотрите Преобразование в целое число для получения дополнительной информации.

Замечание:

Поскольку определенные типы имеют неопределенное поведение при преобразовании в целое число (int), то же самое происходит и при преобразовании в число с плавающей запятой (float).

Сравнение чисел с плавающей точкой

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

Для сравнения чисел с плавающей запятой используется верхняя граница относительной ошибки при округлении. Эта величина называется машинной эпсилон или единицей округления (unit roundoff) и представляет собой самую маленькую допустимую разницу при расчетах.

$a и $b равны до 5-ти знаков после запятой.

<?php
$a 
1.23456789;
$b 1.23456780;
$epsilon 0.00001;

if (
abs($a $b) < $epsilon) {
    echo 
"true";
}
?>

NaN

Некоторые числовые операции могут возвращать значение, представляемое константой NAN. Данный результат означает неопределенное или непредставимое значение в операциях с плавающей точкой. Любое строгое или нестрогое сравнение данного значения с другим значением, кроме true, включая его самого, возвратит false.

Так как NAN представляет собой неограниченное количество различных значений, то NAN не следует сравнивать с другими значениями, включая ее саму. Вместо этого, для определения ее наличия необходимо использовать функцию is_nan().