Menu

PHPのnumber_format():3桁カンマ区切りと小数点

number_format(1234567.891, 2)は"1,234,567.89"を返します。指定した小数点以下の桁数に丸め、3桁ごとの区切りを付けます。4つの引数、ヨーロッパ式と日本式の書式、丸め方、結果が文字列である理由を学びます。

このページのコードはエディタで実行できます - 編集してすぐに結果を確認できます。

number_format($number, $decimals)は、3桁ごとの区切りと固定の小数点以下の桁数を付けた文字列として数値を返します:number_format(1234567.891, 2)は"1,234,567.89"を返します。引数が1つなら整数に丸めます:number_format(1234567.891)は"1,234,568"です。

4つの引数

number_format(
    float $num,
    int $decimals = 0,
    ?string $decimal_separator = ".",
    ?string $thousands_separator = ","
): string

3つ目の引数は整数部分と小数部分の間の文字、4つ目は3桁ごとのグループの間の文字です。どちらも、空文字列やマルチバイト文字を含め、どんな文字列でもかまいません。下の区切り文字を編集して、それぞれの書式を確認してください。

ロケールのデータ(CLDR)では、数値が2行に分かれないよう、フランス語には細いノーブレークスペース(U+202F)が、ロシア語にはノーブレークスペース(U+00A0)が使われます。HTMLでは、普通の空白の代わりに"\u{202F}"や"\u{00A0}"を区切り文字として渡します。

桁区切りなしで数値を整形する

4つ目の引数に''を渡します。小数点以下の桁数が固定された素の数値になり、決済ゲートウェイ、CSVのエクスポート、<input type="number">の値が期待する形です。

最後の行では、キャストの前のround()が重要です。19.9 * 100は1989.9999999999998として保存されるので、(int)だけだと1989に切り捨てられてしまいます。

number_formatの丸め方

number_format()はround()と同じく0から遠い方向へ丸めるので、0.5は1に、-2.5は-3になります。また2.675のような値のわずかな2進数の誤差も補正するので、sprintf('%.2f')と結果が食い違うことがあります。

2.675は2進数で正確に保存できず、保存される値はわずかに小さくなります。sprintf()は保存された値を整形して2.67になり、number_format()とround()は書いたとおりの2.675として扱います。特定の丸め方が必要なら、先に自分でround()、floor()、ceil()を呼び(丸めと数学関数を参照)、その結果をnumber_format()に渡します。

金額やほかの通貨を整形する

number_format()は通貨について何も知らないので、記号は自分で付けます。マイナス記号は通貨記号の前に置き、円には小数部分がないことを覚えておきましょう。

あらゆる国について記号の位置が正しい、ロケールに対応した出力には、intl拡張のNumberFormatterがすべてを引き受けてくれます。

$fmt = new NumberFormatter('de_DE', NumberFormatter::CURRENCY);
echo $fmt->formatCurrency(1234.5, 'EUR'); // 1.234,50 € (a no-break space before €)

これにはintl拡張が必要で、どこにでも入っているわけではないので、自分で記号を付けるnumber_format()が移植性の高い選択です。

結果は数値ではなく文字列

number_format()でいちばんよくあるバグは、値を整形してからそれで計算することです。"1,234.50"は数値文字列ではないので、PHPはカンマの前の1しか読みません。

<?php
echo number_format(1234.5, 2) + 1;
Warning: A non-numeric value encountered in /home/index.php on line 2
2

そのような文字列をnumber_format()に渡し直すのはさらに悪く、TypeError: number_format(): Argument #1 ($num) must be of type int|float, string givenが投げられます。計算には元の数値を残しておき、出力する瞬間にだけ整形しましょう。フォームやファイルから整形済みの文字列を受け取ったら、先に区切り文字を取り除きます。

パディング、位置揃え、数値の前のプラス記号が必要なら、代わりにsprintf()を使います。桁区切りは付けませんが、幅と符号を制御できます。

よくある質問

PHPで数値をカンマ区切りにするには?

number_format($n)を呼びます:number_format(1234567)は"1,234,567"を返します。小数点以下の桁数は2つ目の引数で指定します:number_format(1234567.891, 2)は"1,234,567.89"を返します。

カンマなしでnumber_formatを使うには?

桁区切りに空文字列を渡します:number_format(1234.5, 2, '.', '')は"1234.50"を返します。決済APIやCSVファイルがたいてい期待するのはこの形です。

number_formatは四捨五入ですか、切り捨てですか?

0から遠い方向へ丸めます:number_format(2.5)は"3"、number_format(-2.5)は"-3"、number_format(2.675, 2)は"2.68"です。代わりに小数部分を切り捨てるには、先にfloor()を使います:number_format(floor(2.679 * 100) / 100, 2)は"2.67"になります。

ヨーロッパ式(1.234,56)で数値を整形するには?

3つ目と4つ目の引数で区切り文字を入れ替えます:number_format(1234.56, 2, ',', '.')は"1.234,56"を返します。フランス式やスイス式では、4つ目の引数に空白やアポストロフィを使います。

number_formatの結果に足し算すると、おかしな結果になるのはなぜですか?

number_format()は"1,234.50"のような文字列を返し、それで計算するとPHPはカンマの前の1しか読まないからです。計算には数値のまま使い、number_format()は出力するときだけ呼びましょう。

Coddyのプログラミング言語のイラスト

Coddyでコードを学ぼう

始める