PHP 8.3.4 Released!

La clase NumberFormatter

(PHP 5 >= 5.3.0, PHP 7, PHP 8, PECL intl >= 1.0.0)

Introducción

Los programas almacenan y operan sobre números utilizando una representación binaria independiente de la configuración regional. Cuando se muestra o imprime un número, éste es convertido a una cadena específica regional. Por ejemplo, el número 12345.67 es "12,345.67" en los Estados Unidos, "12 345,67" en Francia y "12.345,67" en Alemania.

Al invocar a los métodos proporcionados por la clase NumberFormatter, se pueden formatear números, valores monetarios y porcentajes de acuerdo a la configuración regional especificada o predeterminada. NumberFormatter es sensible a la configuración regional, por lo que se necesita crear un nuevo objeto NumberFormatter para cada región. Los métodos de NumberFormatter dan formato a números de tipo primitivo, tales como los de tipo double, e imprimien el número como una cadena específica según la región.

Para los valores monetarios se puede utilizar el tipo de formato de moneda para crear un formateador que devuelva una cadena con el número formateado y el símbolo de moneda apropiada. Por supuesto, la clase NumberFormatter ignora los tipos de cambio monetarios, por lo que el número impreso es el mismo sin tener en cuenta la moneda especificada. Esto significa que el mismo número tiene diferentes valores monetarios dependiendo de la moneda regional. Si el numero fuese el 9988776.65, los resultados serían:

  • 9 988 776,65 € en Francia
  • 9.988.776,65 € en Alemania
  • $9,988,776.65 en los Estados Unidos

Para dar formato a los porcentajes, se debe crear un formateador específico de la región con el tipo de formato de porcentaje. Con este formateador, una fracción decimal como 0.75 será mostrada como 75%.

Para un formateo más complejo, como los números escritos con palabras, se usan los formateadores de números basados en reglas.

Sinopsis de la Clase

class NumberFormatter {
/* Métodos */
public __construct(string $locale, int $style, string $pattern = ?)
public static create(string $locale, int $style, string $pattern = ?): NumberFormatter
public formatCurrency(float $value, string $currency): string
public format(number $value, int $type = ?): string
public getAttribute(int $attr): int
public getErrorCode(): int
public getLocale(int $type = ?): string
public getPattern(): string
public getSymbol(int $attr): string
public getTextAttribute(int $attr): string
public parseCurrency(string $value, string &$currency, int &$position = ?): float
public parse(string $value, int $type = ?, int &$position = ?): mixed
public setAttribute(int $attr, int $value): bool
public setPattern(string $pattern): bool
public setSymbol(int $attr, string $value): bool
public setTextAttribute(int $attr, string $value): bool
}

Constantes predefinidas

Estos estilos son utilzados por la función numfmt_create() para definir el tipo del formateador.

NumberFormatter::PATTERN_DECIMAL (integer)
Formato decimal definido por un patrón
NumberFormatter::DECIMAL (integer)
Formato decimal
NumberFormatter::CURRENCY (integer)
Formato de moneda
NumberFormatter::PERCENT (integer)
Formato de porcentaje
NumberFormatter::SCIENTIFIC (integer)
Formato científico
NumberFormatter::SPELLOUT (integer)
Formato basado en reglas de números escritos con palabras
NumberFormatter::ORDINAL (integer)
Formato basado en reglas de números ordinales
NumberFormatter::DURATION (integer)
Formato basado en reglas de duración
NumberFormatter::PATTERN_RULEBASED (integer)
Formato basado en reglas definido por un patrón
NumberFormatter::DEFAULT_STYLE (integer)
Formato predeterminado para la configuración regional
NumberFormatter::IGNORE (integer)
Alias de PATTERN_DECIMAL

Estas constantes definen cómo se procesan o formatean los números. Deberían usarse como argumentos de numfmt_format() y numfmt_parse().

NumberFormatter::TYPE_DEFAULT (integer)
Deriva el tipo de número del tipo de la variable
NumberFormatter::TYPE_INT32 (integer)
Formatear/procesar como un valor integer de 32 bits
NumberFormatter::TYPE_INT64 (integer)
Formatear/procesar como un valor integer de 64 bits
NumberFormatter::TYPE_DOUBLE (integer)
Formatear/procesar como un valor de coma flotante
NumberFormatter::TYPE_CURRENCY (integer)
FFormatear/procesar como un valor de moneda

Atributos de formato numérico usados por numfmt_get_attribute() y numfmt_set_attribute().

NumberFormatter::PARSE_INT_ONLY (integer)
Procesar sólo los enteros.
NumberFormatter::GROUPING_USED (integer)
Usar un separador de agrupación.
NumberFormatter::DECIMAL_ALWAYS_SHOWN (integer)
Mostrar siempre la coma (punto) decimal.
NumberFormatter::MAX_INTEGER_DIGITS (integer)
Número máximo de dígitos enteros.
NumberFormatter::MIN_INTEGER_DIGITS (integer)
Número mínimo de dígitos enteros.
NumberFormatter::INTEGER_DIGITS (integer)
Dígitos enteros.
NumberFormatter::MAX_FRACTION_DIGITS (integer)
Número máximo de dígitos fraccionarios.
NumberFormatter::MIN_FRACTION_DIGITS (integer)
Número mínimo de dígitos fraccionarios.
NumberFormatter::FRACTION_DIGITS (integer)
Dígitos fraccionarios.
NumberFormatter::MULTIPLIER (integer)
Multiplicador.
NumberFormatter::GROUPING_SIZE (integer)
Tamaño de la agrupación.
NumberFormatter::ROUNDING_MODE (integer)
Modo de redondeo.
NumberFormatter::ROUNDING_INCREMENT (integer)
Incremento del redondeo.
NumberFormatter::FORMAT_WIDTH (integer)
El ancho al que se ajusta la salida de format().
NumberFormatter::PADDING_POSITION (integer)
La posición en la que el relleno tendrá lugar. Véase las constantes de posición de relleno para los posibles valores de los argumentos.
NumberFormatter::SECONDARY_GROUPING_SIZE (integer)
Tamaño de agrupación secundario.
NumberFormatter::SIGNIFICANT_DIGITS_USED (integer)
Utilizar dígitos significativos.
NumberFormatter::MIN_SIGNIFICANT_DIGITS (integer)
Número mínimo de dígitos significativos.
NumberFormatter::MAX_SIGNIFICANT_DIGITS (integer)
Número máximo de dígitos significativos.
NumberFormatter::LENIENT_PARSE (integer)
Modo de proceso poco riguroso usado por los formatos basados en reglas.

Atributos de texto de formato numérico utilizados por numfmt_get_text_attribute() y numfmt_set_text_attribute().

NumberFormatter::POSITIVE_PREFIX (integer)
Prefijo positivo.
NumberFormatter::POSITIVE_SUFFIX (integer)
Sufijo positivo.
NumberFormatter::NEGATIVE_PREFIX (integer)
Prefijo negativo.
NumberFormatter::NEGATIVE_SUFFIX (integer)
Sufijo negativo.
NumberFormatter::PADDING_CHARACTER (integer)
El carácter usado para rellenar el ancho del formato.
NumberFormatter::CURRENCY_CODE (integer)
El código ISO de la moneda.
NumberFormatter::DEFAULT_RULESET (integer)
El conjunto de reglas predeterminadas. Sólo está disponible con formateadores basados en reglas.
NumberFormatter::PUBLIC_RULESETS (integer)
Los conjuntos de reglas públicas. Sólo está disponible con formateadores basados en reglas. Este atributo es de sólo lectura. Los conjuntos de reglas públicas son devueltos como una cadena simple, con cada conjunto de reglas deliminado por ';' (semicolon).

Símbolos de formato numérico utilizados por numfmt_get_symbol() y numfmt_set_symbol().

NumberFormatter::DECIMAL_SEPARATOR_SYMBOL (integer)
El separador decimal.
NumberFormatter::GROUPING_SEPARATOR_SYMBOL (integer)
El separador de agrupación.
NumberFormatter::PATTERN_SEPARATOR_SYMBOL (integer)
El separador de patrones.
NumberFormatter::PERCENT_SYMBOL (integer)
El signo de porcentaje.
NumberFormatter::ZERO_DIGIT_SYMBOL (integer)
Cero.
NumberFormatter::DIGIT_SYMBOL (integer)
Carácter que representa un dígito en el patrón.
NumberFormatter::MINUS_SIGN_SYMBOL (integer)
El símbolo menos.
NumberFormatter::PLUS_SIGN_SYMBOL (integer)
El símbolo más.
NumberFormatter::CURRENCY_SYMBOL (integer)
El símbolo de moneda.
NumberFormatter::INTL_CURRENCY_SYMBOL (integer)
El símbolo internacional de moneda.
NumberFormatter::MONETARY_SEPARATOR_SYMBOL (integer)
El separador monetario.
NumberFormatter::EXPONENTIAL_SYMBOL (integer)
El símbolo exponencial.
NumberFormatter::PERMILL_SYMBOL (integer)
El símbolo por millón.
NumberFormatter::PAD_ESCAPE_SYMBOL (integer)
El carácter de relleno de escape.
NumberFormatter::INFINITY_SYMBOL (integer)
Símbolo de infinito.
NumberFormatter::NAN_SYMBOL (integer)
Símbolo de no-es-un-número (NaN).
NumberFormatter::SIGNIFICANT_DIGIT_SYMBOL (integer)
Símbolo de dígito significativo.
NumberFormatter::MONETARY_GROUPING_SEPARATOR_SYMBOL (integer)
El separador de agrupación monetaria.

Los valores del modo de redondeo utilizados por numfmt_get_attribute() y numfmt_set_attribute() con el atributo NumberFormatter::ROUNDING_MODE.

NumberFormatter::ROUND_CEILING (integer)
Modo de redondeo para redondear hacia el infinito positivo.
NumberFormatter::ROUND_DOWN (integer)
Modo de redondeo para redondear hacia cero.
NumberFormatter::ROUND_FLOOR (integer)
Modo de redondeo para redondear hacia el infinito negativo.
NumberFormatter::ROUND_HALFDOWN (integer)
Modo de redondeo para redondear hacia el "vecino más cercano" a menos que ambos vecinos sean equidistantes, en cuyo caso se redondea hacia abajo.
NumberFormatter::ROUND_HALFEVEN (integer)
Modo de redondeo para redondear hacia el "vecino más cercano" a menos que ambos vecinos sean equidistantes, en cuyo caso se redondea hacia el vecino par.
NumberFormatter::ROUND_HALFUP (integer)
Modo de redondeo para redondear hacia el "vecino más cercano" a menos que ambos vecinos sean equidistantes, en cuyo caso se redondea hacia arriba.
NumberFormatter::ROUND_UP (integer)
Modo de redondeo para redondear lejos del cero.

Valores de posición de relleno utilizados por numfmt_get_attribute() y numfmt_set_attribute() con el atributo NumberFormatter::PADDING_POSITION.

NumberFormatter::PAD_AFTER_PREFIX (integer)
Los caracteres de relleno se insertan después del prefijo.
NumberFormatter::PAD_AFTER_SUFFIX (integer)
Los caracteres de relleno se insertan después del sufijo.
NumberFormatter::PAD_BEFORE_PREFIX (integer)
Los caracteres de relleno se insertan antes del prefijo.
NumberFormatter::PAD_BEFORE_SUFFIX (integer)
Los caracteres de relleno se insertan antes del sufijo.

Tabla de contenidos

add a note

User Contributed Notes 9 notes

up
48
giorgio dot liscio at email dot it
12 years ago
this class seems to be painful: it is not, formatting and parsing are highly customizable, but what you probably need is really simple:

if you want to localize a number use:

<?php
$a
= new \NumberFormatter("it-IT", \NumberFormatter::DECIMAL);
echo
$a->format(12345.12345) . "<br>"; // outputs 12.345,12
$a->setAttribute(\NumberFormatter::MIN_FRACTION_DIGITS, 0);
$a->setAttribute(\NumberFormatter::MAX_FRACTION_DIGITS, 100); // by default some locales got max 2 fraction digits, that is probably not what you want
echo $a->format(12345.12345) . "<br>"; // outputs 12.345,12345
?>

if you want to print money use:

<?php
$a
= new \NumberFormatter("it-IT", \NumberFormatter::CURRENCY);
echo
$a->format(12345.12345) . "<br>"; // outputs €12.345,12
?>

if you have money data stored as (for example) US dollars and you want to print them using the it-IT notation, you need to use

<?php
$a
= new \NumberFormatter("it-IT", \NumberFormatter::CURRENCY);
echo
$a->formatCurrency(12345, "USD") . "<br>"; // outputs $ 12.345,00 and it is formatted using the italian notation (comma as decimal separator)
?>

another useful example about currency (how to obtain the currency name by a locale string):

<?php
$frontEndFormatter
= new \NumberFormatter("it-IT", \NumberFormatter::CURRENCY);
$adminFormatter = new \NumberFormatter("en-US", \NumberFormatter::CURRENCY);
$symbol = $adminFormatter->getSymbol(\NumberFormatter::INTL_CURRENCY_SYMBOL); // got USD
echo $frontEndFormatter->formatCurrency(12345.12345, $symbol) . "<br>";
?>
up
1
stan at dragnev dot ca
3 years ago
Here's an example of how to use PATTERN_DECIMAL to print a number with two fraction digits, use () for negative numbers and pad to five characters to the left of the decimal point, using spaces as the padding character:

<?php

$fmt
= new NumberFormatter("en-CA", NumberFormatter::PATTERN_DECIMAL, "* #####.00 ;(* #####.00)");
echo
$fmt->format(-45.1);

// Outputs: " (45.10)"

?>

Note that the ; in the pattern denotes the beginning of a subpattern, which is used for negative numbers. Hence the brackets around the pattern after the semicolon.
up
0
Einenlum
1 month ago
Be aware that (at least with the locale 'fr-FR') NumberFormatter doesn't use spaces. It doesn't even use non breakable spaces (NBSP). It uses narrow non breakable spaces (NNBSP). This broke my tests.

<?php

$formatter
= new NumberFormatter(
'fr-FR',
NumberFormatter::DEFAULT_STYLE
);

$value = $formatter->format(100_000); // '100 000'

// If you want to replace narrow non breakable spaces with non breakable spaces:

str_replace("\u{202F}", "\u{00A0}", $value);

// If you want to replace it with a normal space

str_replace("\u{202F}", " ", $value);
up
0
gwyneth dot llewelyn at gwynethllewelyn dot net
1 year ago
When using the `NumberFormatter` class for pretty-printing currency in PHP 7.3 and 8+, it's not clear from the documentation that you can use the empty string "" as the locale for the constructor, and that will retrieve the default locale (whatever it has been set to in your environment).

`formatCurrency()`, by contrast, does not accept the empty string for the default currency symbol; it will display a 'generic' currency symbol instead (¤).

Tested with PHP 7.4.30, 8.0.21, 8.1.8 under Ubuntu Linux and 8.1.8 under macOS Big Sur (11.6.8). I tried under other alternatives (e.g. Linux running on ARM chips, PHP 7.3.3) but sadly the `NumberFormatter` library does not seem to be present (or could not be found) on those systems...
up
2
sudheer at binaryvibes dot co dot in
13 years ago
Sample script to print number in English.

<?php
$f
= new NumberFormatter("en", NumberFormatter::SPELLOUT);
echo
$f->format(123456);

?>

Produces the result:
one hundred twenty-three thousand four hundred fifty-six
up
-2
AF
3 years ago
Please pay attention to the Arabic decimal separator (https://en.wikipedia.org/wiki/Decimal_separator#Other_numeral_systems).

All the following conditions are true:
<?php
(new \NumberFormatter("ar_AE", \NumberFormatter::DEFAULT_STYLE))->getSymbol(\NumberFormatter::DECIMAL_SEPARATOR_SYMBOL) === '٫';
(new
\NumberFormatter("ar_AE", \NumberFormatter::DEFAULT_STYLE))->getSymbol(\NumberFormatter::DECIMAL_SEPARATOR_SYMBOL) == '٫';

(new
\NumberFormatter("ar_AE", \NumberFormatter::DEFAULT_STYLE))->getSymbol(\NumberFormatter::DECIMAL_SEPARATOR_SYMBOL) !== ',';
(new
\NumberFormatter("ar_AE", \NumberFormatter::DEFAULT_STYLE))->getSymbol(\NumberFormatter::DECIMAL_SEPARATOR_SYMBOL) != ',';
?>
up
-3
Joey
6 years ago
Be warned that this class sometimes lacks sufficient error output. I recently instantiated it while invalid pattern to the constructor.

php -r '$nf = new \NumberFormatter("tlh-KX.UTF8", \NumberFormatter::IGNORE, "{,,#;#}");var_dump($nf->format(5));'

Fatal error: Call to a member function format() on null in Command line code on line 1

Rather than emitting an error message or throwing an exception null is returned after calling new.

I'm not sure if it's fixed in PHP 7 but it's something to watch out for. Make sure you check your parameters very closely.
up
-1
jimbo2150 at gmail dot com
1 year ago
The NumberFormatter class can be used to convert integer numbers to Roman numerals without a custom function using an array of symbols and associated values:

<?php

function intToRomanNumeral(int $num) {
static
$nf = new NumberFormatter('@numbers=roman', NumberFormatter::DECIMAL);
return
$nf->format($num);
}

echo
intToRomanNumeral(2); // II

echo intToRomanNumeral(5); // V

echo intToRomanNumeral(10); // X

echo intToRomanNumeral(50); // L

echo intToRomanNumeral(57); // LVII
echo intToRomanNumeral(58); // LVIII

echo intToRomanNumeral(100); // C

echo intToRomanNumeral(150); // CL

echo intToRomanNumeral(1000); // M

echo intToRomanNumeral(10000); // ↂ

?>
up
-11
Adam
7 years ago
Good to know Numberformatter::SPELLOUT using soft hypens.

So, if you want to avoid it use preg_replace:

<?php
$azaz
= new NumberFormatter("hu-HU", NumberFormatter::SPELLOUT);
$text = preg_replace('~\x{00AD}~u', '', $azaz->format(123456));
print
$text;
?>
Output without preg_replace:
egy-­száz-­huszon-­három-­ezer négy-­száz-­ötven-­hat

Output with preg_replace:
egyszázhuszonháromezer négyszázötvenhat
To Top