PHP Conference Japan 2024

money_format

(PHP 4 >= 4.3.0, PHP 5, PHP 7)

money_format将数字格式化为货币字符串

警告

此函数自 PHP 7.4.0 起已弃用,自 PHP 8.0.0 起已移除。强烈建议不要依赖此函数。

描述

money_format(string $format, float $number): string

money_format() 返回 number 的格式化版本。此函数包装了 C 库函数 strfmon(),区别在于此实现一次只转换一个数字。

参数

format

格式规范由以下序列组成

  • 一个 % 字符

  • 可选标志

  • 可选字段宽度

  • 可选左精度

  • 可选右精度

  • 一个必需的转换字符

标志

可以使用以下一个或多个可选标志

=f

字符 = 后跟一个用作数字填充字符的(单字节)字符 f。默认填充字符为空格。

^

禁用分组字符的使用(由当前区域设置定义)。

+(

指定正数和负数的格式样式。如果使用 +,则将使用区域设置的等效于 +- 的内容。如果使用 (,则负金额用括号括起来。如果没有给出规范,则默认为 +

!

禁止输出字符串中的货币符号。

-

如果存在,它将使所有字段左对齐(向右填充),而不是默认的字段右对齐(向左填充)。

字段宽度

w

指定最小字段宽度的十进制数字字符串。除非使用标志 -,否则字段将右对齐。默认值为 0(零)。

左精度

#n

小数字符(例如小数点)左侧预期的最大位数 (n)。它通常用于使用填充字符使格式化输出保持在同一列对齐,如果位数小于 n。如果实际位数大于 n,则忽略此规范。

如果未使用 ^ 标志禁止分组,则将在添加任何填充字符之前插入分组分隔符。即使填充字符是数字,也不会将分组分隔符应用于填充字符。

为了确保对齐,格式化输出中数字之前或之后的任何字符(如货币或符号符号)都将根据需要用空格字符填充,以使它们的正负格式长度相等。

右精度

.p

一个句点后跟小数字符后的位数 (p)。如果 p 的值为 0(零),则将省略小数字符及其右侧的数字。如果没有包含右精度,则默认值将由使用的当前区域设置决定。在格式化之前,将要格式化的金额四舍五入到指定的位数。

转换字符

i

根据区域设置的国际货币格式格式化数字(例如,对于 USA 区域设置:USD 1,234.56)。

n

根据区域设置的国家/地区货币格式格式化数字(例如,对于 de_DE 区域设置:EU1.234,56)。

%

返回 % 字符。

number

要格式化的数字。

返回值

返回格式化的字符串。格式化字符串之前和之后的字符将保持不变。非数字 number 会导致返回 null 并发出 E_WARNING

变更日志

版本 描述
7.4.0 此函数已被弃用。请改用 NumberFormatter::formatCurrency()

示例

示例 #1 money_format() 示例

我们将使用不同的区域设置和格式规范来说明此函数的使用。

<?php

$number
= 1234.56;

// 让我们打印 en_US 区域设置的国际格式
setlocale(LC_MONETARY, 'en_US');
echo
money_format('%i', $number) . "\n";
// USD 1,234.56

// 带有 2 位小数的意大利语国家/地区格式`
setlocale(LC_MONETARY, 'it_IT');
echo
money_format('%.2n', $number) . "\n";
// Eu 1.234,56

// 使用负数
$number = -1234.5672;

// US 国家/地区格式,对负数使用 ()
// 并对左精度使用 10 位数字
setlocale(LC_MONETARY, 'en_US');
echo
money_format('%(#10n', $number) . "\n";
// ($ 1,234.57)

// 与上面类似的格式,添加使用 2 位右
// 精度和 '*' 作为填充字符
echo money_format('%=*(#10.2n', $number) . "\n";
// ($********1,234.57)

// 让我们左对齐,宽度为 14 个位置,左精度为 8 位数字
// 右精度为 2 位,没有分组字符
// 并对 de_DE 区域设置使用国际格式。
setlocale(LC_MONETARY, 'de_DE');
echo
money_format('%=*^-14#8.2i', 1234.56) . "\n";
// Eu 1234,56****

// 让我们在转换规范之前和之后添加一些内容
setlocale(LC_MONETARY, 'en_GB');
$fmt = 'The final value is %i (after a 10%% discount)';
echo
money_format($fmt, 1234.56) . "\n";
// The final value is GBP 1,234.56 (after a 10% discount)

?>

注释

注意:

函数 money_format() 仅在系统具有 strfmon 功能时才定义。例如,Windows 没有,因此 money_format() 在 Windows 中未定义。

注意:

区域设置设置的 LC_MONETARY 类别会影响此函数的行为。在使用此函数之前,请使用 setlocale() 设置为适当的默认区域设置。

另请参阅

添加注释

用户贡献注释 16 条注释

tim
9 年前
对于我们大多数美国人来说,我们不希望看到货币符号为“USD”,所以“%i”不起作用。以下是我使用的有效方法,可以得到大多数人期望看到的数字格式。

$number = 123.4
setlocale(LC_MONETARY, 'en_US.UTF-8');
money_format('%.2n', $number);

输出
$123.40

这会在开头生成一个美元符号,并在结尾生成 2 位数字。
Rafael M. Salvioni
15 年前
这是一个之前发布的一些函数,但已修复了各种错误。

感谢 Stuart Roe 报告打印信号的错误。

<?php
/*
That it is an implementation of the function money_format for the
platforms that do not it bear.

The function accepts to same string of format accepts for the
original function of the PHP.

(Sorry. my writing in English is very bad)

The function is tested using PHP 5.1.4 in Windows XP
and Apache WebServer.
*/
function money_format($format, $number)
{
$regex = '/%((?:[\^!\-]|\+|\(|\=.)*)([0-9]+)?'.
'(?:#([0-9]+))?(?:\.([0-9]+))?([in%])/';
if (
setlocale(LC_MONETARY, 0) == 'C') {
setlocale(LC_MONETARY, '');
}
$locale = localeconv();
preg_match_all($regex, $format, $matches, PREG_SET_ORDER);
foreach (
$matches as $fmatch) {
$value = floatval($number);
$flags = array(
'fillchar' => preg_match('/\=(.)/', $fmatch[1], $match) ?
$match[1] : ' ',
'nogroup' => preg_match('/\^/', $fmatch[1]) > 0,
'usesignal' => preg_match('/\+|\(/', $fmatch[1], $match) ?
$match[0] : '+',
'nosimbol' => preg_match('/\!/', $fmatch[1]) > 0,
'isleft' => preg_match('/\-/', $fmatch[1]) > 0
);
$width = trim($fmatch[2]) ? (int)$fmatch[2] : 0;
$left = trim($fmatch[3]) ? (int)$fmatch[3] : 0;
$right = trim($fmatch[4]) ? (int)$fmatch[4] : $locale['int_frac_digits'];
$conversion = $fmatch[5];

$positive = true;
if (
$value < 0) {
$positive = false;
$value *= -1;
}
$letter = $positive ? 'p' : 'n';

$prefix = $suffix = $cprefix = $csuffix = $signal = '';

$signal = $positive ? $locale['positive_sign'] : $locale['negative_sign'];
switch (
true) {
case
$locale["{$letter}_sign_posn"] == 1 && $flags['usesignal'] == '+':
$prefix = $signal;
break;
case
$locale["{$letter}_sign_posn"] == 2 && $flags['usesignal'] == '+':
$suffix = $signal;
break;
case
$locale["{$letter}_sign_posn"] == 3 && $flags['usesignal'] == '+':
$cprefix = $signal;
break;
case
$locale["{$letter}_sign_posn"] == 4 && $flags['usesignal'] == '+':
$csuffix = $signal;
break;
case
$flags['usesignal'] == '(':
case
$locale["{$letter}_sign_posn"] == 0:
$prefix = '(';
$suffix = ')';
break;
}
if (!
$flags['nosimbol']) {
$currency = $cprefix .
(
$conversion == 'i' ? $locale['int_curr_symbol'] : $locale['currency_symbol']) .
$csuffix;
} else {
$currency = '';
}
$space = $locale["{$letter}_sep_by_space"] ? ' ' : '';

$value = number_format($value, $right, $locale['mon_decimal_point'],
$flags['nogroup'] ? '' : $locale['mon_thousands_sep']);
$value = @explode($locale['mon_decimal_point'], $value);

$n = strlen($prefix) + strlen($currency) + strlen($value[0]);
if (
$left > 0 && $left > $n) {
$value[0] = str_repeat($flags['fillchar'], $left - $n) . $value[0];
}
$value = implode($locale['mon_decimal_point'], $value);
if (
$locale["{$letter}_cs_precedes"]) {
$value = $prefix . $currency . $space . $value . $suffix;
} else {
$value = $prefix . $value . $space . $currency . $suffix;
}
if (
$width > 0) {
$value = str_pad($value, $width, $flags['fillchar'], $flags['isleft'] ?
STR_PAD_RIGHT : STR_PAD_LEFT);
}

$format = str_replace($fmatch[0], $value, $format);
}
return
$format;
}

?>
todoventas at xarxa-cat dot net
10 年前
在 Rafael M. Salvioni 的函数中,localeconv(); 在我的运行 PHP 5.4.13 的 Windows XP SP3 上返回了一个无效的数组,因此为了防止警告消息:implode(): Invalid arguments passed,我只是手动添加了 $locale。对于其他语言,只需使用正确的设置填充数组即可。

<?

$locale = array(
'decimal_point' => '.',
'thousands_sep' => '',
'int_curr_symbol' => 'EUR',
'currency_symbol' => '€',
'mon_decimal_point' => ',',
'mon_thousands_sep' => '.',
'positive_sign' => '',
'negative_sign' => '-',
'int_frac_digits' => 2,
'frac_digits' => 2,
'p_cs_precedes' => 0,
'p_sep_by_space' => 1,
'p_sign_posn' => 1,
'n_sign_posn' => 1,
'grouping' => array(),
'mon_grouping' => array(0 => 3, 1 => 3)

);
?>
jeremy
16 年前
如果 money_format 似乎无法正常工作,请确保您定义了有效的区域设置。例如,在 Debian 上,“en_US”不是有效的区域设置 - 您需要“en_US.UTF-8”或“en_US.ISO-8559-1”。

这让我沮丧了一段时间。Debian 在 /usr/share/i18n/SUPPORTED 中列出了有效的区域设置;如果它无法正常工作,请在那里找到您的区域设置。
jsb17NO at SPAMcornell dot edu
11 年前
要删除零值小数,请使用以下方法
<?php
/*
与 php number_format() 相同,但如果以 .0、.00、.000 等结尾...,则完全删除小数
返回字符串类型,四舍五入的数字 - 与 php number_format() 相同:
示例:
number_format_drop_zero_decimals(54.378, 2) ==> '54.38'
number_format_drop_zero_decimals(54.00, 2) ==> '54'
*/
function number_format_drop_zero_decimals($n, $n_decimals)
{
return ((
floor($n) == round($n, $n_decimals)) ? number_format($n) : number_format($n, $n_decimals));
}
?>
结果
number_format_drop_zero_decimals(54.377, 2) ==> 54.38
number_format_drop_zero_decimals('54.377', 2) ==> 54.38
number_format_drop_zero_decimals(54.377, 3) ==> 54.377
number_format_drop_zero_decimals(54.007, 2) ==> 54.01
number_format_drop_zero_decimals(54.000, 2) ==> 54
number_format_drop_zero_decimals(54.00, 2) ==> 54
number_format_drop_zero_decimals(54.0, 2) ==> 54
number_format_drop_zero_decimals(54.1, 2) ==> 54.10
number_format_drop_zero_decimals(54., 2) ==> 54
number_format_drop_zero_decimals(54, 2) ==> 54
number_format_drop_zero_decimals(54, 3) ==> 54
number_format_drop_zero_decimals(54 + .13, 2) ==> 54.13
number_format_drop_zero_decimals(54 + .00, 2) ==> 54
number_format_drop_zero_decimals(54.0007, 4) ==> 54.0007
number_format_drop_zero_decimals(54.0007, 3) ==> 54.001
number_format_drop_zero_decimals(54.00007, 3) ==> 54 // 注意
~B
12 年前
我们发现,从 Ubuntu 10.04 php -v 5.3.2 切换到 Ubuntu 12.04 php -v 5.3.10 后,这不再起作用了

<?php setlocale(LC_MONETARY, 'en_US'); ?>

发现使用

<?php setlocale(LC_MONETARY, 'en_US.UTF-8'); ?>

运行良好
andrey.dobrozhanskiy [-a-t-] gmail com
14 年前
此函数使用逗号分割整数值。例如

<?php
echo formatMoney(1050); # 1,050
echo formatMoney(1321435.4, true); # 1,321,435.40
echo formatMoney(10059240.42941, true); # 10,059,240.43
echo formatMoney(13245); # 13,245

function formatMoney($number, $fractional=false) {
if (
$fractional) {
$number = sprintf('%.2f', $number);
}
while (
true) {
$replaced = preg_replace('/(-?\d+)(\d\d\d)/', '$1,$2', $number);
if (
$replaced != $number) {
$number = $replaced;
} else {
break;
}
}
return
$number;
}
?>
Felix Duterloo
8 年前
对 Rafael M. Salvioni 在 Windows 上的 money_format 解决方案的改进:当在格式化中未选择货币符号时,当区域设置将其置于位置 3 或 4 时,负号也会丢失。将 $currency = ''; 更改为:$currency = $cprefix .$csuffix;

function money_format($format, $number) {
$regex = '/%((?:[\^!\-]|\+|\(|\=.)*)([0-9]+)?' .
'(?:#([0-9]+))?(?:\.([0-9]+))?([in%])/';
if (setlocale(LC_MONETARY, 0) == 'C') {
setlocale(LC_MONETARY, '');
}
$locale = localeconv();
preg_match_all($regex, $format, $matches, PREG_SET_ORDER);
foreach ($matches as $fmatch) {
$value = floatval($number);
$flags = array(
'fillchar' => preg_match('/\=(.)/', $fmatch[1], $match) ?
$match[1] : ' ',
'nogroup' => preg_match('/\^/', $fmatch[1]) > 0,
'usesignal' => preg_match('/\+|\(/', $fmatch[1], $match) ?
$match[0] : '+',
'nosimbol' => preg_match('/\!/', $fmatch[1]) > 0,
'isleft' => preg_match('/\-/', $fmatch[1]) > 0
);
$width = trim($fmatch[2]) ? (int) $fmatch[2] : 0;
$left = trim($fmatch[3]) ? (int) $fmatch[3] : 0;
$right = trim($fmatch[4]) ? (int) $fmatch[4] : $locale['int_frac_digits'];
$conversion = $fmatch[5];

$positive = true;
if ($value < 0) {
$positive = false;
$value *= -1;
}
$letter = $positive ? 'p' : 'n';

$prefix = $suffix = $cprefix = $csuffix = $signal = '';

$signal = $positive ? $locale['positive_sign'] : $locale['negative_sign'];
switch (true) {
case $locale["{$letter}_sign_posn"] == 1 && $flags['usesignal'] == '+'
$prefix = $signal;
break;
case $locale["{$letter}_sign_posn"] == 2 && $flags['usesignal'] == '+'
$suffix = $signal;
break;
case $locale["{$letter}_sign_posn"] == 3 && $flags['usesignal'] == '+'
$cprefix = $signal;
break;
case $locale["{$letter}_sign_posn"] == 4 && $flags['usesignal'] == '+'
$csuffix = $signal;
break;
case $flags['usesignal'] == '('
case $locale["{$letter}_sign_posn"] == 0
$prefix = '(';
$suffix = ')';
break;
}
if (!$flags['nosimbol']) {
$currency = $cprefix .
($conversion == 'i' ? $locale['int_curr_symbol'] : $locale['currency_symbol']) .
$csuffix;
} else {
$currency = $cprefix .$csuffix;
}
$space = $locale["{$letter}_sep_by_space"] ? ' ' : '';

$value = number_format($value, $right, $locale['mon_decimal_point'], $flags['nogroup'] ? '' : $locale['mon_thousands_sep']);
$value = @explode($locale['mon_decimal_point'], $value);

$n = strlen($prefix) + strlen($currency) + strlen($value[0]);
if ($left > 0 && $left > $n) {
$value[0] = str_repeat($flags['fillchar'], $left - $n) . $value[0];
}
$value = implode($locale['mon_decimal_point'], $value);
if ($locale["{$letter}_cs_precedes"]) {
$value = $prefix . $currency . $space . $value . $suffix;
} else {
$value = $prefix . $value . $space . $currency . $suffix;
}
if ($width > 0) {
$value = str_pad($value, $width, $flags['fillchar'], $flags['isleft'] ?
STR_PAD_RIGHT : STR_PAD_LEFT);
}

$format = str_replace($fmatch[0], $value, $format);
}
return $format;
}
richard dot selby at uk dot clara dot net
18 年前
仔细检查您计划在任何版本的 PHP 上运行代码时是否定义了 money_format()。您可能会感到惊讶。

例如,它在我的 Linux 代码机上工作,但在运行 BSD 4.11 变体的服务器上却不起作用。(这可能是因为 strfmon 未定义 - 请参阅本页顶部的注释)。这不仅仅是 Windows/Unix 问题。
匿名
1 年前
Rafael M. Salvioni 的代码在值是正数且提供的格式包含 ( 标志时存在一个小错误。仅当值为负数时,值才应括在括号中。这应该可以解决它

<?php
if (!function_exists('money_format'))
{
function
money_format($format, $number)
{
$regex = '/%((?:[\^!\-]|\+|\(|\=.)*)([0-9]+)?'.
'(?:#([0-9]+))?(?:\.([0-9]+))?([in%])/';
if (
setlocale(LC_MONETARY, 0) == 'C') {
setlocale(LC_MONETARY, '');
}
$locale = localeconv();
preg_match_all($regex, $format, $matches, PREG_SET_ORDER);
foreach (
$matches as $fmatch) {
$value = floatval($number);
$flags = array(
'fillchar' => preg_match('/\=(.)/', $fmatch[1], $match) ?
$match[1] : ' ',
'nogroup' => preg_match('/\^/', $fmatch[1]) > 0,
'usesignal' => preg_match('/\+|\(/', $fmatch[1], $match) ?
$match[0] : '+',
'nosimbol' => preg_match('/\!/', $fmatch[1]) > 0,
'isleft' => preg_match('/\-/', $fmatch[1]) > 0
);
$width = trim($fmatch[2]) ? (int)$fmatch[2] : 0;
$left = trim($fmatch[3]) ? (int)$fmatch[3] : 0;
$right = trim($fmatch[4]) ? (int)$fmatch[4] : $locale['int_frac_digits'];
$conversion = $fmatch[5];

$positive = true;
if (
$value < 0) {
$positive = false;
$value *= -1;
}
$letter = $positive ? 'p' : 'n';

$prefix = $suffix = $cprefix = $csuffix = $signal = '';

$signal = $positive ? $locale['positive_sign'] : $locale['negative_sign'];
switch (
true) {
case
$locale["{$letter}_sign_posn"] == 1 && $flags['usesignal'] == '+':
$prefix = $signal;
break;
case
$locale["{$letter}_sign_posn"] == 2 && $flags['usesignal'] == '+':
$suffix = $signal;
break;
case
$locale["{$letter}_sign_posn"] == 3 && $flags['usesignal'] == '+':
$cprefix = $signal;
break;
case
$locale["{$letter}_sign_posn"] == 4 && $flags['usesignal'] == '+':
$csuffix = $signal;
break;
case
$flags['usesignal'] == '(' && !$positive:
case
$locale["{$letter}_sign_posn"] == 0:
$prefix = '(';
$suffix = ')';
break;
}
if (!
$flags['nosimbol']) {
$currency = $cprefix .
(
$conversion == 'i' ? $locale['int_curr_symbol'] : $locale['currency_symbol']) .
$csuffix;
} else {
$currency = '';
}
$space = $locale["{$letter}_sep_by_space"] ? ' ' : '';

$value = number_format($value, $right, $locale['mon_decimal_point'],
$flags['nogroup'] ? '' : $locale['mon_thousands_sep']);
$value = @explode($locale['mon_decimal_point'], $value);

$n = strlen($prefix) + strlen($currency) + strlen($value[0]);
if (
$left > 0 && $left > $n) {
$value[0] = str_repeat($flags['fillchar'], $left - $n) . $value[0];
}
$value = implode($locale['mon_decimal_point'], $value);
if (
$locale["{$letter}_cs_precedes"]) {
$value = $prefix . $currency . $space . $value . $suffix;
} else {
$value = $prefix . $value . $space . $currency . $suffix;
}
if (
$width > 0) {
$value = str_pad($value, $width, $flags['fillchar'], $flags['isleft'] ?
STR_PAD_RIGHT : STR_PAD_LEFT);
}

$format = str_replace($fmatch[0], $value, $format);
}
return
$format;
}
}
?>
phpdeveloperbalaji at gmail dot com
13 年前
你好,

对于南亚货币,此函数可能非常方便。

它将处理负数以及浮点数(派斯)。

<?php
function my_money_format($number)
{
if(
strstr($number,"-"))
{
$number = str_replace("-","",$number);
$negative = "-";
}

$split_number = @explode(".",$number);

$rupee = $split_number[0];
$paise = @$split_number[1];

if(@
strlen($rupee)>3)
{
$hundreds = substr($rupee,strlen($rupee)-3);
$thousands_in_reverse = strrev(substr($rupee,0,strlen($rupee)-3));
for(
$i=0; $i<(strlen($thousands_in_reverse)); $i=$i+2)
{
$thousands .= $thousands_in_reverse[$i].$thousands_in_reverse[$i+1].",";
}
$thousands = strrev(trim($thousands,","));
$formatted_rupee = $thousands.",".$hundreds;

}
else
{
$formatted_rupee = $rupee;
}

if((int)
$paise>0)
{
$formatted_paise = ".".substr($paise,0,2);
}

return
$negative.$formatted_rupee.$formatted_paise;

}
?>

谢谢,
swapnet
16 年前
考虑为一些使用 ##,##,###.## 货币格式的南亚国家格式化货币。
以下代码生成类似 Rs. 4,54,234.00 等等。

<?php
function convertcash($num, $currency){
if(
strlen($num)>3){
$lastthree = substr($num, strlen($num)-3, strlen($num));
$restunits = substr($num, 0, strlen($num)-3); // 提取最后三位数字
$restunits = (strlen($restunits)%2 == 1)?"0".$restunits:$restunits; // 将剩余数字以 2 为一组拆分,在开头添加一个零以保持 2 的分组。

$expunit = str_split($restunits, 2);
for(
$i=0; $i<sizeof($expunit); $i++){
$explrestunits .= (int)$expunit[$i].","; // 创建每组 2 个数字,并在末尾添加逗号
}

$thecash = $explrestunits.$lastthree;
} else {
$thecash = $convertnum;
}

return
$currency.$thecash.".00"; // 写入最终格式,其中 $currency 是货币符号。
}
?>

现在调用该函数作为 convertcash($row['price'], 'Rs '); // 这是我使用印度卢比前缀调用的数据库中的价格,价格必须是纯数字格式,例如 454234。
kaigillmann at googlemail dot com
10 年前
如果您得到“EUR”而不是欧元符号,请将区域设置设置为 utf8 字符集,如下所示

<?php
setlocale
(LC_MONETARY, 'de_DE.utf8');
echo
money_format('%+n', 1234.56);
?>
scot from ezyauctionz.co.nz
17 年前
这正是我刚刚编写的一段方便的小代码,因为我无法找到任何其他适合我情况的代码。
这将处理用户传递给脚本的货币值,重新格式化任何逗号的使用,以便在通过检查浮点数的输入验证系统时不会被破坏。

它并非万无一失,但将处理大多数用户输入的常见输入,例如 1,234,567(输出 1234567)或 1,234.00(输出 1234.00),甚至处理 12,34(输出 12.34),我预计它可以处理负数,但尚未测试,因为在我的情况下它没有用于此目的。

当其他选项(例如 money_format())不合适或不可用时,此方法有效。

<?php
///////////////
// 代码开始 将所有价格金额转换为格式良好的值
function converttonum($convertnum,$fieldinput){
$bits = explode(",",$convertnum); // 将输入值拆分以允许检查

$first = strlen($bits[0]); // 获取第一个逗号之前的部分(千位/百万位)
$last = strlen($bits[1]); // 获取第一个逗号之后的部分(千位(或如果用户错误使用则为小数)

if ($last <3){ // 检查逗号是否用作小数点
$convertnum = str_replace(",",".",$convertnum);
}
else{
// 假设逗号是千位分隔符,因此将其删除
$convertnum = str_replace(",","",$convertnum);
}

$_POST[$fieldinput] = $convertnum; // 重新定义变量的值,使其成为新的更正值
}

@
converttonum($_POST[inputone],"inputone");
@
converttonum($_POST[inputtwo],"inputtwo");
@
converttonum($_POST[inputthree],"inputthree");
// 代码结束
//////////////

?>

这适用于英语用法,可能需要调整才能与其他类型一起使用。
justsomeone
7 年前
对具有超过两位小数的浮点值使用 money_format 函数可能导致舍入错误。
也许此函数可以帮助您避免这些错误

<?php
// 产品基础价格为 12.95
$price = 1295;

// 数量也是整数,但转换后为 11.91
$quantity = 1191;

// 结果:154.2345
// 等同于 12.95 * 11.91
$sum = ($price / 100) * ($quantity /100);

// 错误结果:154.23
money_format('%!i', $sum);

// 错误结果:154.23
number_format($sum, 2);

// 错误结果:154.23
bcmul($price / 100, $quantity / 100, 2);

// 正确结果:154.24
money_format_rounded('%!i', $sum);

/**
* 将数字格式化为货币字符串。将每个小数位单独四舍五入到定义的精度。
*
* @param string $format money_format 函数的格式
* @param float|int|string $number 要格式化的数字
* @param int $maxPrecision 四舍五入到 $maxPrecision 个小数位。默认为:2
* @param int $roundingType round 函数的舍入类型。默认为:\PHP_ROUND_HALF_UP
*
* @return string
*/
function money_format_rounded($format, $number, $maxPrecision = 2, $roundingType = \PHP_ROUND_HALF_UP)
{
$strlen = strlen($number);
if (
$strlen === 0) {
return
money_format($format, $number);
}

$length = $strlen - strrpos($number, '.') - 1;
if (
$length <= 0) {
return
money_format($format, $number);
}

$rounded = $number;
for (
$i = --$length; $i >= $maxPrecision; $i--) {
$rounded = round($rounded, $i, $roundingType);
}

return
money_format($format, $rounded);
}
sainthyoga2003 at gmail dot com
4 年前
请注意,从 PHP 7.3 开始,此方法已弃用,从 PHP 7.4 开始,此方法将引发弃用错误,因此,请设置您的 PHP Web 服务器以取消跟踪 E_DEPRECATED 错误报告。
To Top