number_format($number, $decimals) возвращает число строкой с разделителем тысяч и фиксированным числом знаков после запятой: number_format(1234567.891, 2) возвращает "1,234,567.89". С одним аргументом функция округляет до целого: number_format(1234567.891) даёт "1,234,568".
Четыре параметра
number_format(
float $num,
int $decimals = 0,
?string $decimal_separator = ".",
?string $thousands_separator = ","
): string
Третий аргумент это символ между целой частью и дробной, четвёртый символ между группами из трёх цифр. Любым из них может быть любая строка, в том числе пустая или многобайтовый символ. Измените разделители ниже, чтобы увидеть каждый стиль:
Данные локалей (CLDR) используют узкий неразрывный пробел (U+202F) для французского и неразрывный пробел (U+00A0) для русского, чтобы число никогда не переносилось на две строки. В HTML передавайте разделителем "\u{202F}" или "\u{00A0}" вместо обычного пробела.
Число без разделителя тысяч
Передайте '' четвёртым аргументом. Получится простое число с фиксированным числом знаков после запятой, именно такое ждут платёжные шлюзы, экспорт в CSV и значения <input type="number">:
В последней строке важен round() перед приведением: 19.9 * 100 хранится как 1989.9999999999998, и один (int) обрезал бы его до 1989.
Как округляет number_format
number_format() округляет половину от нуля, как round(), поэтому 0.5 становится 1, а -2.5 становится -3. Ещё она исправляет крошечную двоичную ошибку в значениях вроде 2.675, поэтому может расходиться со sprintf('%.2f'):
2.675 нельзя точно сохранить в двоичном виде; сохранённое значение чуть меньше. sprintf() форматирует это сохранённое значение и получает 2.67, а number_format() и round() считают его тем 2.675, которое вы написали. Если нужно определённое правило округления, сами вызовите round(), floor() или ceil() (смотрите округление и математику) и передайте результат в number_format().
Деньги и другие валюты
number_format() ничего не знает о валютах, поэтому символ добавляйте сами. Ставьте знак минус перед символом и помните, что у иены нет дробной части:
Для вывода с учётом локали и правильным положением символа в каждой стране всю работу делает NumberFormatter из расширения intl:
$fmt = new NumberFormatter('de_DE', NumberFormatter::CURRENCY);
echo $fmt->formatCurrency(1234.5, 'EUR'); // 1.234,50 € (a no-break space before €)
Ему нужно расширение intl, которое установлено не везде, поэтому number_format() со своим символом это переносимый выбор.
Результат это строка, а не число
Самая частая ошибка с number_format(): отформатировать значение, а потом с ним считать. "1,234.50" не числовая строка, поэтому PHP читает только 1 до запятой:
<?php
echo number_format(1234.5, 2) + 1;
Warning: A non-numeric value encountered in /home/index.php on line 2
2
Передать такую строку обратно в number_format() ещё хуже: она выбрасывает TypeError: number_format(): Argument #1 ($num) must be of type int|float, string given. Храните исходное число для математики и форматируйте только в момент вывода. Если отформатированная строка пришла из формы или файла, сначала уберите разделители:
Для дополнения, выравнивания или знака плюс перед числом используйте sprintf(): она не добавляет разделители тысяч, но управляет шириной и знаком.
Часто задаваемые вопросы
Как отформатировать число с разделителями разрядов в PHP?
Вызовите number_format($n): number_format(1234567) возвращает "1,234,567". Передайте второй аргумент для знаков после запятой: number_format(1234567.891, 2) возвращает "1,234,567.89".
Как использовать number_format без запятой?
Передайте пустую строку как разделитель тысяч: number_format(1234.5, 2, '.', '') возвращает "1234.50". Именно такую форму обычно ждут платёжные API и CSV-файлы.
number_format округляет или отбрасывает?
Округляет, половину от нуля: number_format(2.5) даёт "3", number_format(-2.5) даёт "-3", а number_format(2.675, 2) даёт "2.68". Чтобы вместо этого отбросить знаки, сначала используйте floor(): number_format(floor(2.679 * 100) / 100, 2) даёт "2.67".
Как форматировать числа по-европейски (1.234,56)?
Поменяйте разделители третьим и четвёртым аргументами: number_format(1234.56, 2, ',', '.') возвращает "1.234,56". Во французском, русском и швейцарском стилях четвёртым аргументом служит пробел или апостроф.
Почему number_format даёт неверный результат, если к нему что-то прибавить?
number_format() возвращает строку вроде "1,234.50", и в арифметике PHP читает из неё только 1 до запятой. Храните число для вычислений и вызывайте number_format() только при выводе.