Signature
number_format(
float $num,
int $decimals = 0,
?string $decimal_separator = ".",
?string $thousands_separator = ","
): stringPurpose
number_format() turns a number into a human-readable string. It groups thousands, rounds to a chosen number of decimal digits, and lets you pick the characters used for the decimal point and the thousands separator. It is a presentation tool: you use it when showing a value to a person, not when storing or calculating it.
Signature
Parameters and defaults
$numis the number to format. Integers and numeric strings are converted to float in the usual non-strict way.$decimalsis how many digits appear after the decimal point. The default is0, so the fraction is rounded away. When it is0, the decimal separator is omitted from the result entirely.$decimal_separatoris the string placed before the decimals. The default is a dot.$thousands_separatoris the string placed between groups of three digits. The default is a comma. Pass an empty string for no grouping.
Since PHP 8.0 you may pass one, two, three or four arguments. Earlier versions did not accept exactly three.
Return value and failure cases
The function always returns a string. Rounding uses the half-up rule, so 2.5 becomes 3 and -2.5 becomes -3. A value that rounds to zero is shown as 0, never -0; this has been the behavior since PHP 7.2.
The function does not return false. Passing something that cannot be treated as a float, such as the string "abc" or an array, raises a TypeError.
As of PHP 8.3, a negative $decimals rounds the number to that many positions before the decimal point. Before 8.3 negative values were treated like 0.
Example 1: default and custom separators
This shows the same value in English notation, European notation and as a plain machine-friendly string without grouping.
$number = 1234567.891;
echo number_format($number), PHP_EOL;
echo number_format($number, 2), PHP_EOL;
echo number_format($number, 2, ',', '.'), PHP_EOL;
echo number_format($number, 2, '.', ''), PHP_EOL;1,234,568 1,234,567.89 1.234.567,89 1234567.89
The first call drops the fraction and rounds up to 1,234,568. The last call uses an empty thousands separator, which is useful when a value goes into a CSV-like text or an input field.
Example 2: rounding, negatives and zero
$values = [
'half' => number_format(2.5),
'negative' => number_format(-1234.567, 2),
'tiny_negative' => number_format(-0.01),
'rounded_up' => number_format(0.129, 2),
];
echo json_encode($values, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), PHP_EOL;{"half":"3","negative":"-1,234.57","tiny_negative":"0","rounded_up":"0.13"}
The minus sign is kept for real negative values, but -0.01 rounded to zero decimals prints as 0.
Example 3: negative decimals
With PHP 8.3 and later, a negative $decimals rounds to tens, hundreds or thousands.
$number = 1234.5678;
$result = [
number_format($number, -1),
number_format($number, -2),
number_format($number, -3),
];
echo json_encode($result, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), PHP_EOL;["1,230","1,200","1,000"]
Notice that the result still has thousands grouping, and the trailing digits become zeros rather than disappearing.
Edge cases
- Zero decimals: no decimal separator appears, even if you passed a custom one.
- Empty separators: an empty string is allowed for both separators and simply removes that piece of formatting.
- Large values and floats: floating-point numbers are approximations, so a value such as
1.005may not round the way decimal arithmetic on paper suggests. - Output is not numeric: a result like
1,234.50is text. Casting it back to a number does not parse the grouping correctly.
Common mistakes
- Formatting before calculating. Format only at the final display step. If you format a subtotal and then add it to something else, you are working with a string that includes separators.
- Using it for money storage. Floats cannot represent many decimal fractions exactly. Store currency as integer minor units, such as cents, and divide only when displaying.
- Assuming locale awareness.
number_format()does not read the user's locale. You must supply the separators yourself for each audience. - Forgetting the default drops decimals.
number_format(9.99)returns10. Always pass$decimalswhen the fraction matters. - Parsing the output. Do not send formatted text to APIs or databases. Keep the raw number and format a copy for display.
Related functions
sprintf()andprintf()format numbers with padding and precision, but they do not group thousands.round()changes the numeric value and returns a float rather than a display string.intdiv()and integer arithmetic are better for exact currency math in minor units.
Recap
number_format() returns a string with grouped thousands and rounded decimals. Defaults are no decimals, a dot and a comma. Rounding is half up, -0 is never returned, and negative $decimals rounds before the decimal point as of PHP 8.3. Use it only for output, and keep exact values in a separate numeric form.
Tested examples
$number = 1234567.891;
echo number_format($number), PHP_EOL;
echo number_format($number, 2), PHP_EOL;
echo number_format($number, 2, ',', '.'), PHP_EOL;
echo number_format($number, 2, '.', ''), PHP_EOL;
1,234,568 1,234,567.89 1.234.567,89 1234567.89
$values = [
'half' => number_format(2.5),
'negative' => number_format(-1234.567, 2),
'tiny_negative' => number_format(-0.01),
'rounded_up' => number_format(0.129, 2),
];
echo json_encode($values, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), PHP_EOL;
{"half":"3","negative":"-1,234.57","tiny_negative":"0","rounded_up":"0.13"}
$number = 1234.5678;
$result = [
number_format($number, -1),
number_format($number, -2),
number_format($number, -3),
];
echo json_encode($result, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), PHP_EOL;
["1,230","1,200","1,000"]