PHP Conference Japan 2024

NumberFormatter 类

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

简介

程序使用与语言环境无关的二进制表示来存储和操作数字。当显示或打印数字时,它会被转换为特定于语言环境的字符串。例如,数字 12345.67 在美国是“12,345.67”,在法国是“12 345,67”,在德国是“12.345,67”。

通过调用 NumberFormatter 类提供的函数,您可以根据指定的或默认的语言环境格式化数字、货币和百分比。NumberFormatter 对语言环境敏感,因此您需要为每个语言环境创建一个新的 NumberFormatter。NumberFormatter 函数格式化基本类型的数字,例如 double,并将数字输出为特定于语言环境的字符串。

对于货币,您可以使用货币格式类型创建格式化程序,该格式化程序返回包含格式化数字和相应货币符号的字符串。当然,NumberFormatter 类不知道汇率,因此,无论指定的货币是什么,输出的数字都相同。这意味着相同的数字在不同的货币语言环境中具有不同的货币价值。如果数字是 9988776.65,则结果将是

  • 在法国为 9 988 776,65 €
  • 在德国为 9.988.776,65 €
  • 在美国为 $9,988,776.65

为了格式化百分比,请使用百分比格式类型创建特定于语言环境的格式化程序。使用此格式化程序,小数分数(例如 0.75)将显示为 75%。

对于更复杂的格式化(如拼写数字),使用基于规则的数字格式化程序。

类概要

class NumberFormatter {
/* 常量 */
public const int PATTERN_DECIMAL;
public const int DECIMAL;
public const int CURRENCY;
public const int PERCENT;
public const int SCIENTIFIC;
public const int SPELLOUT;
public const int ORDINAL;
public const int DURATION;
public const int PATTERN_RULEBASED;
public const int IGNORE;
public const int CURRENCY_ACCOUNTING;
public const int DEFAULT_STYLE;
public const int ROUND_CEILING;
public const int ROUND_FLOOR;
public const int ROUND_DOWN;
public const int ROUND_UP;
public const int ROUND_TOWARD_ZERO;
public const int ROUND_HALFEVEN;
public const int ROUND_HALFODD;
public const int ROUND_HALFDOWN;
public const int ROUND_HALFUP;
public const int PAD_BEFORE_PREFIX;
public const int PAD_AFTER_PREFIX;
public const int PAD_BEFORE_SUFFIX;
public const int PAD_AFTER_SUFFIX;
public const int PARSE_INT_ONLY;
public const int GROUPING_USED;
public const int MAX_INTEGER_DIGITS;
public const int MIN_INTEGER_DIGITS;
public const int INTEGER_DIGITS;
public const int MAX_FRACTION_DIGITS;
public const int MIN_FRACTION_DIGITS;
public const int FRACTION_DIGITS;
public const int MULTIPLIER;
public const int GROUPING_SIZE;
public const int ROUNDING_MODE;
public const int ROUNDING_INCREMENT;
public const int FORMAT_WIDTH;
public const int PADDING_POSITION;
public const int LENIENT_PARSE;
public const int POSITIVE_PREFIX;
public const int POSITIVE_SUFFIX;
public const int NEGATIVE_PREFIX;
public const int NEGATIVE_SUFFIX;
public const int PADDING_CHARACTER;
public const int CURRENCY_CODE;
public const int DEFAULT_RULESET;
public const int PUBLIC_RULESETS;
public const int PERCENT_SYMBOL;
public const int ZERO_DIGIT_SYMBOL;
public const int DIGIT_SYMBOL;
public const int MINUS_SIGN_SYMBOL;
public const int PLUS_SIGN_SYMBOL;
public const int CURRENCY_SYMBOL;
public const int EXPONENTIAL_SYMBOL;
public const int PERMILL_SYMBOL;
public const int PAD_ESCAPE_SYMBOL;
public const int INFINITY_SYMBOL;
public const int NAN_SYMBOL;
public const int TYPE_DEFAULT;
public const int TYPE_INT32;
public const int TYPE_INT64;
public const int TYPE_DOUBLE;
public const int TYPE_CURRENCY;
/* 方法 */
public __construct(string $locale, int $style, ?string $pattern = null)
public static create(string $locale, int $style, ?string $pattern = null): ?NumberFormatter
public format(int|float $num, int $type = NumberFormatter::TYPE_DEFAULT): string|false

public formatCurrency(float $amount, string $currency): string|false
public getAttribute(int $attribute): int|float|false
public getErrorCode(): int
public getSymbol(int $symbol): string|false
public getTextAttribute(int $attribute): string|false
public parse(string $string, int $type = NumberFormatter::TYPE_DOUBLE, int &$offset = null): int|float|false
public parseCurrency(string $string, string &$currency, int &$offset = null): float|false
public setAttribute(int $attribute, int|float $value): bool
public setPattern(string $pattern): bool
public setSymbol(int $symbol, string $value): bool
public setTextAttribute(int $attribute, string $value): bool
}

预定义常量

格式类型

这些样式由 numfmt_create() 用于定义格式化程序的类型。

NumberFormatter::PATTERN_DECIMAL int
由模式定义的十进制格式
NumberFormatter::DECIMAL int
十进制格式
NumberFormatter::CURRENCY int
货币格式
NumberFormatter::PERCENT int
百分比格式
NumberFormatter::SCIENTIFIC int
科学计数法格式
NumberFormatter::SPELLOUT int
拼写规则格式
NumberFormatter::ORDINAL int
序数规则格式
NumberFormatter::DURATION int
持续时间规则格式
NumberFormatter::PATTERN_RULEBASED int
由模式定义的基于规则的格式
NumberFormatter::CURRENCY_ACCOUNTING int
用于会计的货币格式,例如,对于负货币金额使用 ($3.00) 而不是 -$3.00。自 PHP 7.4.1 和 ICU 53 起可用。
NumberFormatter::DEFAULT_STYLE int
区域设置的默认格式
NumberFormatter::IGNORE int
PATTERN_DECIMAL 的别名

数字格式说明符

这些常量定义了数字如何被解析或格式化。它们应该用作 numfmt_format()numfmt_parse() 的参数。

NumberFormatter::TYPE_DEFAULT int
从变量类型派生类型
NumberFormatter::TYPE_INT32 int
格式化/解析为 32 位整数
NumberFormatter::TYPE_INT64 int
格式化/解析为 64 位整数
NumberFormatter::TYPE_DOUBLE int
格式化/解析为浮点值
NumberFormatter::TYPE_CURRENCY int
格式化/解析为货币值。自 PHP 8.3.0 起已弃用

数字格式属性

numfmt_get_attribute()numfmt_set_attribute() 使用的数字格式属性。

NumberFormatter::PARSE_INT_ONLY int
仅解析整数。
NumberFormatter::GROUPING_USED int
使用分组分隔符。
NumberFormatter::DECIMAL_ALWAYS_SHOWN int
始终显示小数点。
NumberFormatter::MAX_INTEGER_DIGITS int
最大整数位数。
NumberFormatter::MIN_INTEGER_DIGITS int
最小整数位数。
NumberFormatter::INTEGER_DIGITS int
整数位数。
NumberFormatter::MAX_FRACTION_DIGITS int
最大小数位数。
NumberFormatter::MIN_FRACTION_DIGITS int
最小小数位数。
NumberFormatter::FRACTION_DIGITS int
小数位数。
NumberFormatter::MULTIPLIER int
乘数。
NumberFormatter::GROUPING_SIZE int
分组大小。
NumberFormatter::ROUNDING_MODE int
舍入模式。
NumberFormatter::ROUNDING_INCREMENT int
舍入增量。
NumberFormatter::FORMAT_WIDTH int
format() 输出填充的宽度。
NumberFormatter::PADDING_POSITION int
填充的位置。请参阅填充位置常量以获取可能的参数值。
NumberFormatter::SECONDARY_GROUPING_SIZE int
次要分组大小。
NumberFormatter::SIGNIFICANT_DIGITS_USED int
使用有效数字。
NumberFormatter::MIN_SIGNIFICANT_DIGITS int
最小有效数字。
NumberFormatter::MAX_SIGNIFICANT_DIGITS int
最大有效数字。
NumberFormatter::LENIENT_PARSE int
基于规则的格式使用的宽松解析模式。

数字格式文本属性

numfmt_get_text_attribute()numfmt_set_text_attribute() 使用的数字格式文本属性。

NumberFormatter::POSITIVE_PREFIX int
正前缀。
NumberFormatter::POSITIVE_SUFFIX int
正后缀。
NumberFormatter::NEGATIVE_PREFIX int
负前缀。
NumberFormatter::NEGATIVE_SUFFIX int
负后缀。
NumberFormatter::PADDING_CHARACTER int
用于填充到格式宽度的字符。
NumberFormatter::CURRENCY_CODE int
ISO 货币代码。
NumberFormatter::DEFAULT_RULESET int
默认规则集。这仅适用于基于规则的格式化程序。
NumberFormatter::PUBLIC_RULESETS int
公共规则集。这仅适用于基于规则的格式化程序。这是一个只读属性。公共规则集作为单个字符串返回,每个规则集名称由“;”分隔(分号)。

舍入模式

numfmt_get_attribute()numfmt_set_attribute() 使用 NumberFormatter::ROUNDING_MODE 属性时的舍入模式值。

NumberFormatter::ROUND_AWAY_FROM_ZERO
NumberFormatter::ROUND_UP 的别名。
NumberFormatter::ROUND_CEILING int
舍入到正无穷大的舍入模式。
NumberFormatter::ROUND_DOWN int
舍入到零的舍入模式。
NumberFormatter::ROUND_FLOOR int
舍入到负无穷大的舍入模式。
NumberFormatter::ROUND_HALFDOWN int
舍入到“最近的邻居”,除非两个邻居等距,在这种情况下向下舍入。
NumberFormatter::ROUND_HALFEVEN int
舍入到“最近的邻居”,除非两个邻居等距,在这种情况下,舍入到偶数邻居。
NumberFormatter::ROUND_HALFODD
舍入到“奇数邻居”的舍入模式。
NumberFormatter::ROUND_HALFUP int
舍入到“最近的邻居”,除非两个邻居等距,在这种情况下向上舍入。
NumberFormatter::ROUND_TOWARD_ZERO
NumberFormatter::ROUND_DOWN 的别名。
NumberFormatter::ROUND_UP int
远离零舍入的舍入模式。

填充说明符

numfmt_get_attribute()numfmt_set_attribute() 使用 NumberFormatter::PADDING_POSITION 属性时的填充位置值。

NumberFormatter::PAD_AFTER_PREFIX int
在前缀之后插入填充字符。
NumberFormatter::PAD_AFTER_SUFFIX int
在后缀之后插入填充字符。
NumberFormatter::PAD_BEFORE_PREFIX int
在之前缀之前插入填充字符。
NumberFormatter::PAD_BEFORE_SUFFIX int
在后缀之前插入填充字符。

变更日志

版本 描述
8.4.0 类常量现在已添加类型。

目录

添加注释

用户贡献的注释 8 条注释

giorgio dot liscio at email dot it
13 年前
这个类看起来很麻烦:其实不然,格式化和解析都是高度可定制的,但你可能真正需要的是非常简单的功能

如果你想本地化数字,可以使用

<?php
$a
= new \NumberFormatter("it-IT", \NumberFormatter::DECIMAL);
echo
$a->format(12345.12345) . "<br>"; // 输出 12.345,12
$a->setAttribute(\NumberFormatter::MIN_FRACTION_DIGITS, 0);
$a->setAttribute(\NumberFormatter::MAX_FRACTION_DIGITS, 100); // 默认情况下,某些区域设置最多有 2 位小数,这可能不是你想要的
echo $a->format(12345.12345) . "<br>"; // 输出 12.345,12345
?>

如果你想打印货币,可以使用

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

如果你有以(例如)美元存储的货币数据,并且你想使用 it-IT 表示法打印它们,你需要使用

<?php
$a
= new \NumberFormatter("it-IT", \NumberFormatter::CURRENCY);
echo
$a->formatCurrency(12345, "USD") . "<br>"; // 输出 $ 12.345,00 并且使用意大利表示法(逗号作为小数分隔符)进行格式化
?>

另一个关于货币的有用示例(如何从区域设置字符串中获取货币名称)

<?php
$frontEndFormatter
= new \NumberFormatter("it-IT", \NumberFormatter::CURRENCY);
$adminFormatter = new \NumberFormatter("en-US", \NumberFormatter::CURRENCY);
$symbol = $adminFormatter->getSymbol(\NumberFormatter::INTL_CURRENCY_SYMBOL); // 获取 USD
echo $frontEndFormatter->formatCurrency(12345.12345, $symbol) . "<br>";
?>
jimbo2150 at gmail dot com
1 年前
NumberFormatter 类可用于将整数转换为罗马数字,而无需使用符号数组和关联值的自定义函数

<?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); // ↂ

?>
stan at dragnev dot ca
4 年前
这是一个如何使用 PATTERN_DECIMAL 打印带有两位小数的数字的示例,对负数使用 () 并将小数点左侧填充到五个字符,使用空格作为填充字符

<?php

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

// 输出: " (45.10)"

?>

请注意,模式中的 ; 表示子模式的开始,用于负数。因此,分号后面的模式周围有括号。
Einenlum
10 个月前
请注意,(至少对于区域设置“fr-FR”)NumberFormatter 不使用空格。它甚至不使用不换行空格 (NBSP)。它使用窄不换行空格 (NNBSP)。这破坏了我的测试。

<?php

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

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

// 如果你想用不换行空格替换窄不换行空格:

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

// 如果你想用普通空格替换它

str_replace("\u{202F}", " ", $value);
sudheer at binaryvibes dot co dot in
13 年前
打印英文数字的示例脚本。

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

?>

产生结果
one hundred twenty-three thousand four hundred fifty-six
gwyneth dot llewelyn at gwynethllewelyn dot net
2 年前
在 PHP 7.3 和 8+ 中使用 `NumberFormatter` 类进行货币的美化打印时,文档中没有明确说明可以使用空字符串 "" 作为构造函数的区域设置,这将检索默认区域设置(无论它在您的环境中设置为什么)。

`formatCurrency()` 则不接受空字符串作为默认货币符号;它将显示一个“通用”货币符号(¤)。

在 Ubuntu Linux 下的 PHP 7.4.30、8.0.21、8.1.8 和 macOS Big Sur (11.6.8) 下的 8.1.8 中进行了测试。我尝试了其他替代方案(例如在 ARM 芯片上运行的 Linux,PHP 7.3.3),但遗憾的是,这些系统上似乎不存在(或找不到)`NumberFormatter` 库……
AF
3 年前
请注意阿拉伯语小数分隔符 (https://en.wikipedia.org/wiki/Decimal_separator#Other_numeral_systems).

以下所有条件均为真
<?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) != ',';
?>
Joey
7 年前
请注意,此类有时缺乏足够的错误输出。我最近在构造函数中使用无效模式实例化它。

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

致命错误:在命令行代码第 1 行调用的成员函数 format() 为 null

在调用 new 之后,返回 null 而不是发出错误消息或抛出异常。

我不确定 PHP 7 中是否已修复,但这是一个需要注意的问题。请务必仔细检查您的参数。
To Top