虽然此函数接受用于货币的浮点数(以便显示美分),但您应该(对于对此至关重要的应用程序)永远不要使用浮点数存储或处理货币,因为可能会出现舍入错误。相反,在内部使用整数(如果整数不够大,则使用 BigInt 类),其中整数表示美分的总数。另一种选择(特别是如果您需要比美分更高的精度)是使用 BC(二进制计算器)数学模块,该模块以 100% 的精度处理任意精度数字。
(PHP 5 >= 5.3.0, PHP 7, PHP 8, PECL intl >= 1.0.0)
NumberFormatter::formatCurrency -- numfmt_format_currency — 格式化货币值
面向对象风格
过程式风格
根据格式化程序规则格式化货币值。
表示格式化货币值的字符串,或在失败时为 false
。
示例 #1 numfmt_format_currency() 示例
<?php
$fmt = numfmt_create( 'de_DE', NumberFormatter::CURRENCY );
echo numfmt_format_currency($fmt, 1234567.891234567890000, "EUR")."\n";
echo numfmt_format_currency($fmt, 1234567.891234567890000, "RUR")."\n";
$fmt = numfmt_create( 'ru_RU', NumberFormatter::CURRENCY );
echo numfmt_format_currency($fmt, 1234567.891234567890000, "EUR")."\n";
echo numfmt_format_currency($fmt, 1234567.891234567890000, "RUR")."\n";
?>
示例 #2 面向对象示例
<?php
$fmt = new NumberFormatter( 'de_DE', NumberFormatter::CURRENCY );
echo $fmt->formatCurrency(1234567.891234567890000, "EUR")."\n";
echo $fmt->formatCurrency(1234567.891234567890000, "RUR")."\n";
$fmt = new NumberFormatter( 'ru_RU', NumberFormatter::CURRENCY );
echo $fmt->formatCurrency(1234567.891234567890000, "EUR")."\n";
echo $fmt->formatCurrency(1234567.891234567890000, "RUR")."\n";
?>
上面的示例将输出
1.234.567,89 € 1.234.567,89 RUR 1 234 567,89€ 1 234 567,89р.
注意:
通过这种格式化方法可以实现的格式无法完全利用底层 ICU 库的可能性,例如格式化带有窄货币符号的货币。
要充分利用它们,请使用 msgfmt_format_message()。
虽然此函数接受用于货币的浮点数(以便显示美分),但您应该(对于对此至关重要的应用程序)永远不要使用浮点数存储或处理货币,因为可能会出现舍入错误。相反,在内部使用整数(如果整数不够大,则使用 BigInt 类),其中整数表示美分的总数。另一种选择(特别是如果您需要比美分更高的精度)是使用 BC(二进制计算器)数学模块,该模块以 100% 的精度处理任意精度数字。
当您想要格式化没有子单位的货币并且货币不是给定区域设置中使用的货币时,您需要 _在_ 设置 NumberFormatter::FRACTION_DIGITS _之前_ 作为 TextAttribute 设置货币代码。
<?php
$fmt = new NumberFormatter('en_US', NumberFormatter::CURRENCY);
$fmt->setTextAttribute(NumberFormatter::CURRENCY_CODE, 'EUR');
$fmt->setAttribute(NumberFormatter::FRACTION_DIGITS, 0);
$fmt->formatCurrency(100, 'EUR');
?>
关于不同格式化[1]的说明实际上并不取决于 PHP 版本,而是取决于 PHP 编译所针对的 icu 库[2] 的版本,因为此库有一个包含不同区域设置的格式化规则的数据库。
[1]: https://php.net/manual/en/numberformatter.formatcurrency.php#116610
[2]: http://site.icu-project.org/
formatCurrency() 不遵循此处发布的货币小数国际标准:https://www.currency-iso.org/en/home/tables/table-a1.html.
要定义小数,我发现我们需要在设置一些 NumberFormat 属性后使用 format() 函数。
例如,“COP”(哥伦比亚比索)定义为使用 2 位小数,但 NumberFormat::formatCurrency() 对这种货币使用 0 位小数(我不知道为什么!)。
这是我使用的代码
$fmt = new \NumberFormatter( 'fr', \NumberFormatter::CURRENCY);
$fmt->setTextAttribute( $fmt::CURRENCY_CODE, 'COP' );
$fmt->setAttribute( $fmt::FRACTION_DIGITS, 2 );
$numberString = $fmt->format( 1234.56 );
输出结果为:1 234,56 $CO
如果将区域设置更改为“en”,则输出为:COP1,234.56
货币符号似乎有虚假支持。
例如,泰铢符号.. ฿ 在泰语区域设置中似乎不受支持,但在其他区域设置(例如简体中文)中则受支持。
<?php
$fmt = new NumberFormatter('th_TH', NumberFormatter::CURRENCY);
echo $fmt->formatCurrency(100, 'THB');
// 输出:THB 100
$fmt = new NumberFormatter('zh_Hans', NumberFormatter::CURRENCY);
echo $fmt->formatCurrency(100, 'THB');
// 输出:฿ 100
?>
这让我百思不得其解。在处理某些英语区域设置(例如“en_US”和“en_CA”等,但肯定不是所有)时,重要的是要注意,PHP 5.5 和 PHP 5.6 之间的负数格式不同。
代码
<?php
$formatter = new NumberFormatter('en_US', NumberFormatter::CURRENCY);
echo $formatter->formatCurrency(-0.99, 'USD'), PHP_EOL;
$formatter = new NumberFormatter('en_CA', NumberFormatter::CURRENCY);
echo $formatter->formatCurrency(-0.99, 'USD'), PHP_EOL;
?>
PHP 5.5 的输出
-$0.99
-US$0.99
PHP 5.6 的输出
($0.99)
(US$0.99)
在设置模式时,不要忘记货币符号和数字之间的空格字符(作为前缀或后缀)不应该可拆分(例如 HTML 中的 )。例如,在 UTF-8 中,您应该使用不间断空格字符 ("\xC2\xA0")
<?php
$fmt = new NumberFormatter('en_US', NumberFormatter::CURRENCY);
$fmt->setPattern(str_replace('¤#',"¤\xC2\xA0#", $fmt->getPattern()));
?>
此函数在 PHP 会话中第一次运行时通常比后续运行慢 1000 多倍,并且每次都使用新创建的格式化程序。
第一次运行的计时结果从 60 毫秒到 195 毫秒不等,而后续运行的时间远低于 100 微秒。
为了比较,创建格式化程序大约需要 100 微秒。
似乎对于包含美元符号“$”的货币符号,结果格式化的数字被破坏了:95.23 被格式化为 .23 而不是 $95.23。作为一种解决方法,您需要通过添加空格来修改模式
<?php
$fmt = new NumberFormatter('en_US', NumberFormatter::CURRENCY);
$fmt->setTextAttribute(NumberFormatter::CURRENCY_CODE, 'CAD');
$fmt->setPattern( str_replace('¤#','¤ #', $fmt->getPattern() ) );
echo $fmt->formatCurrency(100, 'CAD');
?>