今日仕事で触ったコードを改修しててハマったこと。
money_formatとは
string money_format ( string $format , float $number )
money_format() は、number をフォーマットして返します。この関数は C のライブラリ関数 strfmon() をラップしたものですが、一度に 変換できる数値がひとつだけであるという点が異なります。
http://php.net/manual/ja/function.money-format.php
との事。
金額を表示するような箇所で使われてて個人的には初めて見た。
ほえーこんな関数あったんだーと思ってたらなんか小数点の処理が不可解だった。
例
setlocale(LC_MONETARY, 'ja_JP');
echo money_format("%n", 1000.4)."\n";
echo money_format("%n", 2500.6)."\n";
echo money_format("%n", 5000.5)."\n";
↓
¥1,000
¥2,501
¥5,000
まぁ普通に分かる。
round()
したあと number_format()
掛けて先頭に¥
付けるイメージなのかなーなんて最初は思ってた。
ハマったのはここから
setlocale(LC_MONETARY, 'ja_JP');
echo money_format("%n", 5001.5)."\n";
echo money_format("%n", 5002.5)."\n";
↓
¥5,002
¥5,002
ファッ!?
更に確認してみた
setlocale(LC_MONETARY, 'ja_JP');
for ($i=0.5; $i<10; $i++) {
echo "orig:".$i." / round:".round($i)." / money_format:".money_format("%n", $i)."\n";
}
↓
orig:0.5 / round:1 / money_format:¥0
orig:1.5 / round:2 / money_format:¥2
orig:2.5 / round:3 / money_format:¥2
orig:3.5 / round:4 / money_format:¥4
orig:4.5 / round:5 / money_format:¥4
orig:5.5 / round:6 / money_format:¥6
orig:6.5 / round:7 / money_format:¥6
orig:7.5 / round:8 / money_format:¥8
orig:8.5 / round:9 / money_format:¥8
orig:9.5 / round:10 / money_format:¥10
うーむ。。。???
金額の為の関数なんだろうけどちょっと挙動が謎過ぎてお金みたいなキッチリ処理して出さないと怒られちゃう系の表示にはあまり使いたくないなーなんて思っちゃった。
追記
コメントにて@hnwさんから教えて頂きました。
これは偶数丸めという奴で、むしろお金の計算に使う丸め方式ですね。
https://ja.wikipedia.org/wiki/%E7%AB%AF%E6%95%B0%E5%87%A6%E7%90%86#.E5.81.B6.E6.95.B0.E3.81.B8.E3.81.AE.E4.B8.B8.E3.82.81.EF.BC.88round_to_even.EF.BC.89端数が0.5より小さいなら切り捨て、端数が0.5より大きいならは切り上げ、端数がちょうど0.5なら切り捨てと切り上げのうち結果が偶数となる方へ丸める。
端数処理ってそんな種類いっぱいあったのね…