number_format

Formats a number with grouped thousands and a fixed number of decimal places.

Signature
number_format(float $num, int $decimals = 0, ?string $decimal_separator = ".", ?string $thousands_separator = ","): string
  • Added in PHP 4.0

Parameters

ParameterTypeDescription
$numfloatThe number being formatted.
$decimalsoptionalint= 0Number of decimal digits. If 0, the decimal separator is omitted. As of PHP 8.3, negative values round num to significant digits before the decimal point.
$decimal_separatoroptional?string= "."The separator placed before the decimal digits.
$thousands_separatoroptional?string= ","The separator placed between groups of three digits.

Return value

stringA formatted string version of num.

Changelog

  • PHP 8.3.0Negative values for decimals are now handled, rounding num to significant digits before the decimal point.
  • PHP 8.0.0Prior to this version, number_format() accepted one, two or four arguments, but not three.
  • PHP 7.2.0No longer returns "-0"; previously values such as -0.01 could format as -0.

number_format turns a float into a display string: it rounds to the requested number of decimals, pads with zeros if needed, and inserts a grouping separator every three digits. It is the fastest way to render prices, totals and counts in a table without dragging in intl.

Locale is your job

The function has no locale awareness at all. The defaults are US-style — . for decimals, , for thousands — and if you need German (1.234.567,89) or French (1 234 567,89) you pass those separators yourself. When you need genuine per-locale formatting, currency symbols and correct grouping for languages that do not group in threes, use NumberFormatter from the intl extension instead.

Rounding, and what comes back

Rounding is half-up on the value as stored, so ordinary float imprecision applies; if the exact cent matters, keep money in integer minor units and only format at the very end. Since PHP 8.3 a negative decimals rounds to the left of the decimal point — number_format(12345, -3) gives 12,000. Since PHP 7.2 a value like -0.01 formats as 0.0 rather than the confusing -0.0.

The return value is a string. Feeding it back into arithmetic is the number-one bug here: the thousands separator makes the numeric cast stop at the comma.

Example

Try it yourself
Loading editor…
Press Run to execute the code.

When to use it

  • Render order totals as "1,234.50" in an invoice table.
  • Format the same figure for a German or French locale by swapping the separator arguments.
  • Show large view or follower counts with thousands grouping in a dashboard.

Frequently asked questions

Why does number_format return the wrong value when I add to it?

Because it returns a string containing separators, and PHP's numeric cast stops at the first comma — "1,234.50" becomes 1. Do all arithmetic on the raw float and format only at output time.

How do I format a number for a European locale?

Pass the separators explicitly: number_format($n, 2, ',', '.') gives 1.234.567,89. number_format itself ignores setlocale, so for real locale-driven output use the intl extension's NumberFormatter class.

What is the difference between number_format and sprintf with %.2f?

sprintf('%.2f', $n) fixes the decimal places but adds no thousands separator and always uses a dot. number_format does both grouping and decimals, and lets you choose the separator characters.

More examples

Aligning a price column

Prints a padded table ending in `9.99` and `1,249.50`. number_format supplies the trailing zero and the thousands comma, printf handles the column widths. Note the price is passed with %s, not %f — it is already a string by then, and %f would re-format it and mangle the comma.

Example · php
<?php
$rows = [['Widget', 4, 9.99], ['Gizmo', 120, 1249.5]];
foreach ($rows as [$name, $qty, $price]) {
    printf("%-8s %5s  %10s\n", $name, number_format($qty), number_format($price, 2));
}

Negative decimals, and the string trap

`12,000` shows the PHP 8.3 negative-decimals rounding; `0.0` shows the PHP 7.2 change that stops -0 appearing. Then the trap: the formatted value is the string "1,234.50", and casting it to float yields 1 because the cast stops at the comma. Strip the separators first to get 1234.5 back.

Example · php
<?php
echo number_format(12345, -3), PHP_EOL;
echo number_format(-0.01, 1), PHP_EOL;

$formatted = number_format(1234.5, 2);
var_dump($formatted);
var_dump((float) $formatted);
var_dump((float) str_replace(',', '', $formatted));

Discussion

  • Be the first to comment on this lesson.