PHP:数字の 切上げ/切捨て/四捨五入 の端数処理

PHP:数字の 切上げ/切捨て/四捨五入 の端数処理

PHPで端数処理:切上げ/切捨て/四捨五入

いつも忘れて調べる 切上げ/切捨て/四捨五入の端数処理。ExcelやMySQLの数式と混同するからたちが悪い。その上、小数点第○位まで出す場合の処理がサッといかない。という事で、調査結果を備忘録に書き溜めます。

言語 四捨五入 切上げ処理 切捨て処理
Excelの場合 ROUND(第一因子,第二因子) ROUNDUP(第一因子,第二因子) ROUNDDOWN(第一因子,第二因子)
PHPの場合 round(第一因子,第二因子) ceil(第一因子*pow(10,第二因子))/pow(10,第二因子) floor(第一因子*pow(10,第二因子))/pow(10,第二因子)

round(第一因子,第二因子, PHP_ROUND_HALF_DOWN)

MYSQLの場合 TRUNCATE(第一因数+係数, 第二因子) TRUNCATE(第一因数+係数, 第二因子) TRUNCATE(第一因数, 0)

以降、具体例は【値:105.53】で実際の処理を記載していきます。

四捨五入

ここまではどの言語でも単純な書き方でとても分かりやすい。と思っていたらMySQLで四捨五入する時はROUNDを使うなとの記事がありました。四捨五入と言えば『ROUND』…ではないのですね。具体例を記載しながら書き方をチェックしていきます。

  • PHP
    1. 整数に丸める ROUND(105.53,0) =116
    2. 10の位を四捨五入 ROUND(105.53,-2) 100
    3. 小数点第2位を四捨五入 ROUND(105.53,1) =105.5
  • MySQL
    1. 整数に丸める TRUNCATE(105.53+0.5, 0)= 116
    2. 10の位を四捨五入 TRUNCATE(105.53+5, -1) = 100
    3. 小数点第2位を四捨五入 TRUNCATE(105.53+0.05, 1)= 105.5
  • Excel
    1. 整数に丸める ROUND(105.53,0) = 116
    2. 10の位を四捨五入 ROUND(105.53,-2) = 100
    3. 小数点第2位を四捨五入 ROUND(105.53,1) = 105.5

ここで大きな疑問が生まれました。プラスの値は分かるけどマイナスの値の四捨五入って何が正しいの?例えば、-1.6の場合、5~9では値を+1すると考えると…0?でも四捨五入だから-2?はるか昔の中学時代、使わない演算ルールは忘却されてます。うす~~くなった学校で教えてもらった四捨五入の説明を思い起こしてみると『1.6を四捨五入 ⇒ (定規を取出して) 0.6cm は1cmの半分よりも1に近い。だから繰上げて1とみなしてあげる』とか言っていたような…。これをマイナス値で考えてみます。

-1.6を四捨五入 ⇒ -0.6は-1の半分よりも-1に近い。だから繰り下げて-1とする。

なるほど、日本JIS企画で決めている企画(JISZ8401)と合致する。混乱したら初心に帰れですね。

切上げ処理

エクセルの式は至極簡単なままですが、PHPでもちょっと複雑な式が出てきました。MySQLと同様に係数を利用するタイプの計算方法です。

  • PHP
    1. 小数点以下を切上げ ceil(105.53) =116
    2. 10の位を切上げ ceil(105.53 /10)*100 =200
    3. 小数点第2位を切上げ ceil(105.53*10)/10 =105.6
  • MySQL
    1. 小数点以下を切上げ TRUNCATE(105.53+0.9, 0)= 116
    2. 10の位を切上げ TRUNCATE(105.53+90, -1) = 200
    3. 小数点第2位を切上げ TRUNCATE(105.53+0.09, 1)= 105.6
  • Excel
    1. 小数点以下を切上げ ROUNDUP(105.53,0) = 116
    2. 10の位を切上げ ROUNDUP(105.53,-2) = 200
    3. 小数点第2位を切上げ ROUNDUP(105.53,1) = 105.6

ceil関数は『端数の切り上げ』を行う関数で小数点以下を切り上げて整数にします。そのため、ceil関数の前処理として切上げしたい値を少数に落とし込みます。PHPの項目2の例では 10.5という値を作ってあげるわけです。MySQLのTRUNSCATEと異なる下準備の方法ですが、なるほど、こんなやり方があるんですね。

PHPには他に、round関数にmodeパラメーターを付けた表記方法【round(9.5, 0, PHP_ROUND_HALF_UP)】もあるようですが、単純な切上げとはならないようです。

切捨て処理

MySQLのTRUNCATE関数は元々切り捨てる計算式なので、切捨て処理では単純な式になりました。一方で整数化の処理を行うPHPのfloor関数は切上げのceilと同じく桁の調整が必要になります。

  • PHP
    1. 小数点以下を切上げ floor(105.53) =115
    2. 10の位を切上げ floor(105.53 /10)*100 =100
    3. 小数点第2位を切上げ floor(105.53*10)/10 =105.5
  • MySQL
    1. 小数点以下を切上げ TRUNCATE(105.53, 0)= 115
    2. 10の位を切上げ TRUNCATE(105.53, -1) = 100
    3. 小数点第2位を切上げ TRUNCATE(105.53, 1)= 105.5
  • Excel
    1. 小数点以下を切上げ ROUNDDOWN(105.53,0) = 116
    2. 10の位を切上げ ROUNDDOWN(105.53,-2) = 200
    3. 小数点第2位を切上げ ROUNDDOWN(105.53,1) = 105.5

PHPの場合、ROUND関数のmodeパラメーターにPHP_ROUND_HALF_DOWN をつけても同様の答えが算出できそうです。

まとめ

調べてみると数のまとめ処理は意外と厄介なものだということがわかりました。

ECシステムを作ろうとすると、どうしても消費税の端数処理が出てきます。今回調べるきっかけとなった楽天市場のスーパーセールサーチ用割引指示など、自分と楽天市場と使っている関数が違う事で『ちゃんとやっているけど撥ねられる』事態は起こるんだろうなぁと容易に推測できました。ここら辺は調整あるのみですね。