LoginSignup
3
2

More than 5 years have passed since last update.

money_formatの小数点処理が謎だった

Last updated at Posted at 2017-09-14

今日仕事で触ったコードを改修しててハマったこと。

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なら切り捨てと切り上げのうち結果が偶数となる方へ丸める。

端数処理ってそんな種類いっぱいあったのね…

3
2
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2