number_format() convierte un número en una cadena con el formato de separadores que espera el usuario: punto de miles y coma decimal en español, coma de miles y punto decimal en inglés. Es la función estándar para mostrar precios, cantidades y porcentajes en PHP, aunque hay detalles que conviene conocer antes de confiar ciegamente en el resultado.
Los cuatro parámetros
<?php
number_format(
float $num,
int $decimals = 0,
string $decimal_separator = '.',
string $thousands_separator = ','
): string
?>
Si solo pasas el número, devuelve un entero sin decimales y con comas como separador de miles (formato anglosajón). Para euros en español necesitas los cuatro argumentos:
<?php $precio = 12890.5; echo number_format($precio); // 12,891 (redondea, sin decimales) echo number_format($precio, 2); // 12,890.50 (anglosajón) echo number_format($precio, 2, ',', '.'); // 12.890,50 (español/Europa) echo number_format($precio, 2, ',', '') . ' €'; // 12890,50 € (sin separador de miles) ?>
Formatear precios en euros
<?php
function precio(float $importe, string $moneda = '€'): string
{
return number_format($importe, 2, ',', '.') . ' ' . $moneda;
}
$productos = [
['nombre' => 'Camiseta', 'precio' => 19.9],
['nombre' => 'Pantalón', 'precio' => 39.95],
['nombre' => 'Zapatillas', 'precio' => 129.99],
['nombre' => 'Abrigo', 'precio' => 2499.0],
];
foreach ($productos as $p) {
echo str_pad($p['nombre'], 15) . precio($p['precio']) . "n";
}
// Camiseta 19,90 €
// Pantalón 39,95 €
// Zapatillas 129,99 €
// Abrigo 2.499,00 €
?>
Combinar con sprintf()
Cuando necesitas mostrar el precio dentro de una cadena más larga, combinar number_format() con sprintf() mantiene el código limpio:
<?php
$base = 450.0;
$iva = 21;
$total = $base * (1 + $iva / 100);
$linea = sprintf(
'Base imponible: %s | IVA (%d%%): %s | Total: %s',
number_format($base, 2, ',', '.'),
$iva,
number_format($total - $base, 2, ',', '.'),
number_format($total, 2, ',', '.')
);
echo $linea;
// Base imponible: 450,00 | IVA (21%): 94,50 | Total: 544,50
?>
Diferencia con money_format() (eliminada en PHP 8)
money_format() existÃa en PHP para formatear cantidades según la configuración regional del sistema (locale). Se marcó como obsoleta en PHP 7.4 y se eliminó en PHP 8.0. Si ves código legacy que la usa, sustitúyela por number_format() con los separadores correctos, o por la clase NumberFormatter de la extensión intl si necesitas soporte completo de locales:
<?php
// PHP 8+: usar NumberFormatter (extensión intl)
$fmt = new NumberFormatter('es_ES', NumberFormatter::CURRENCY);
echo $fmt->formatCurrency(12890.5, 'EUR');
// 12.890,50 €
?>
Por qué number_format() no resuelve la precisión de los floats
number_format() redondea al número de decimales indicado, pero el número interno sigue siendo un float con los problemas de representación binaria de siempre. Para cálculos financieros precisos usa bcmath o trabaja en céntimos (enteros):
<?php
$a = 0.1 + 0.2;
echo $a; // 0.3 (pero no exactamente)
echo number_format($a, 2, ',', '.'); // 0,30 (parece correcto)
echo ($a == 0.3 ? 'igual' : 'distinto'); // distinto
// Con bcmath
$suma = bcadd('0.1', '0.2', 10);
echo $suma; // 0.3000000000
?>
La documentación oficial de number_format() incluye ejemplos de comportamiento con distintos locales y las notas sobre la precisión de los tipos flotantes.
