Числа в PHP: типы данных, преобразование и безопасное использование

Раздел: Работа с данными

Основные способы работы с числами

Наиболее эффективный и безопасный подход для работы с числами в PHP - использование комбинации filter_var с соответствующими флагами для валидации и последующего приведения типа. Этот метод позволяет одновременно проверить, является ли значение целым числом или числом с плавающей точкой, и получить корректный результат или false в случае ошибки. Например:

$input = '42';
$int = filter_var($input, FILTER_VALIDATE_INT);
if ($int === false) {
    echo 'Некорректное целое число';
} else {
    echo $int; // 42
}

$float = filter_var('3.14', FILTER_VALIDATE_FLOAT);
var_dump($float); // float(3.14)

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

Как преобразовать строку в целое число без проверки?

Функция intval и приведение типа (int) преобразуют значение в целое число, отбрасывая всё, что не является цифрой в начале строки. Однако это может привести к неожиданным результатам, если входные данные содержат нечисловые символы.

$str = '123abc';
echo intval($str); // 123
echo (int)$str;    // 123

$str2 = 'abc123';
echo intval($str2); // 0

Типичная ошибка: использование intval или (int) на строке, начинающейся с букв, даёт 0, что может быть воспринято как корректное значение. Решение - предварительная проверка через filter_var или ctype_digit.

Как преобразовать строку в число с плавающей точкой?

Аналогично используются floatval и приведение (float):

$str = '3.14abc';
echo floatval($str); // 3.14
echo (float)$str;    // 3.14

$str2 = 'abc3.14';
echo floatval($str2); // 0

Проблема: те же риски, что и с целыми. Кроме того, из-за особенностей двоичного представления чисел с плавающей точкой результат может содержать ошибки округления (например, 0.1 + 0.2 ≠ 0.3). Для финансовых вычислений рекомендуется использовать расширение BCMath.

Как проверить, является ли значение числом?

PHP предоставляет несколько функций: is_numeric, is_int, is_float, ctype_digit.

$values = ['42', '3.14', '1e3', 'abc', 42, 3.14];
foreach ($values as $v) {
    echo is_numeric($v) ? 'число' : 'не число';
    echo ' | ';
    echo is_int($v) ? 'int' : '';
    echo is_float($v) ? 'float' : '';
    echo "\n";
}

Ошибка: is_numeric возвращает true для чисел в научной нотации (например, '1e3'), что может быть нежелательно при проверке пользовательского ввода. ctype_digit проверяет только целые положительные числа без знака. Для строгой валидации лучше использовать filter_var.

Как округлить число до заданного количества знаков?

Функция round округляет по правилам математического округления. ceil округляет вверх, floor - вниз. Для форматирования с фиксированным количеством десятичных знаков используется number_format.

$num = 3.14159;
echo round($num, 2);        // 3.14
echo ceil($num);            // 4
echo floor($num);           // 3
echo number_format($num, 2, '.', ''); // 3.14

Проблема: round может давать неожиданные результаты для чисел с плавающей точкой (например, round(2.5, 0, PHP_ROUND_HALF_UP) vs round(2.5, 0, PHP_ROUND_HALF_EVEN)). Рекомендуется явно указывать режим округления при необходимости.

Как избежать ошибок точности при работе с float?

Для точных вычислений (финансы, научные расчёты) используется расширение BCMath (binary calculator) или GMP для целых чисел произвольной длины.

$a = '0.1';
$b = '0.2';
$sum = bcadd($a, $b, 2); // 0.30
echo $sum; // 0.30

// Сравнение float
if (bccomp($a, $b, 10) == 0) {
    echo 'равны';
} else {
    echo 'не равны';
}

Ошибка: стандартное сравнение чисел с плавающей точкой через == может дать false, даже если теоретически они равны (0.1 + 0.2 == 0.3 - false). Решение - использование bccomp или сравнение с эпсилоном: abs($a - $b) < 1e-10.

Расширенные примеры работы с числами в PHP.

Пример 1: Точные вычисления с BCMath

Пример
$price = '19.99';
$quantity = '3';
$taxRate = '0.07';

$subtotal = bcmul($price, $quantity, 2);        // 59.97
$tax = bcmul($subtotal, $taxRate, 2);          // 4.20
$total = bcadd($subtotal, $tax, 2);            // 64.17

echo "Итоговая сумма: $total";
Итоговая сумма: 64.17

Пример 2: Форматирование чисел с учётом локали

Пример
setlocale(LC_NUMERIC, 'de_DE.UTF-8');
$num = 1234567.89;
echo number_format($num, 2, ',', '.'); // 1.234.567,89

// Использование NumberFormatter
$fmt = new NumberFormatter('de_DE', NumberFormatter::CURRENCY);
echo $fmt->formatCurrency(1234567.89, 'EUR'); // 1.234.567,89 €
1.234.567,89 €

Пример 3: Генерация криптостойких случайных чисел

Пример
// Случайное целое от 1 до 100
$secureInt = random_int(1, 100);
echo $secureInt;

// Случайное число с плавающей точкой от 0 до 1 (не криптостойко, но для примера)
$randomFloat = mt_rand() / mt_getrandmax();
// Для криптостойкого float: unpack('f', random_bytes(4))[1] (требуется осторожность)
(например) 47

Пример 4: Обработка чисел из CSV-файла

Пример
$csv = "123;45.67;abc\n89;0.01;xyz";
$lines = explode("\n", $csv);
$numbers = [];
foreach ($lines as $line) {
    $parts = explode(';', $line);
    foreach ($parts as $part) {
        $num = filter_var($part, FILTER_VALIDATE_FLOAT);
        if ($num !== false) {
            $numbers[] = $num;
        }
    }
}
print_r($numbers);
Array
(
    [0] => 123
    [1] => 45.67
    [2] => 89
    [3] => 0.01
)

Пример 5: Работа с большими целыми числами через GMP

Пример
$factorial = gmp_fact(100);
echo gmp_strval($factorial);
// 93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000
(гигантское число)

Пример 6: Преобразование систем счисления

Пример
$hex = 'ff';
$dec = hexdec($hex);        // 255
$bin = decbin($dec);        // 11111111
$oct = decoct($dec);        // 377

echo "HEX: $hex -> DEC: $dec -> BIN: $bin -> OCT: $oct";
HEX: ff -> DEC: 255 -> BIN: 11111111 -> OCT: 377

Пример 7: Арифметика на 64-битных числах с переполнением

Пример
// PHP автоматически преобразует int в float при переполнении
$big = PHP_INT_MAX;
$bigger = $big + 1;
var_dump($bigger); // float(9.2233720368548E+18) - потеря точности

// Для сохранения точности используем BCMath
$bcResult = bcadd((string)$big, '1', 0);
echo $bcResult; // 9223372036854775808 (точное значение)
float(9.2233720368548E+18)
9223372036854775808

Работа с числами в PHP - comments

En
Php числа (php)