五捨六入...?1,000円未満を切り捨て...?ってどうするの??
エンジニアの伊藤です。
皆さんの給与明細書には、健康保険、厚生年金や所得税などの控除項目が記載されています。
...見たことないという人は、給与明細書をもう一度確かめてみてくださいね。
支給額からこれらの控除項目を差し引いた金額が、実際の給与として支払われる金額、いわゆる手取りになります。
この記事では、この控除項目の計算について取り上げたいと思います。計算手順もいろいろと厄介なのですが、ここではそのうちの端数計算を取り上げたいと思います。
端数計算
端数計算というと四捨五入、切り上げ、切り捨てなどがすぐに思い浮かびますね。 Rubyでもround、ceil、floorなどのメソッドが用意されていてとても便利です。
四捨五入
10.5.round
=> 11
10.4.round
=> 10
切り上げ
10.5.ceil
=> 11
切り捨て
10.5.floor
=> 10
しかし、例えば全国健康保険協会(協会けんぽ)の保険料額表の注意書きにはこのように書いてあります。
「事業主が、給与から被保険者負担分を控除する場合、被保険者負担分の端数が50銭以下の場合は切り捨て、50銭を超える場合は切り上げて1円となります。」
「50銭以下の場合は切り捨て、50銭を超える場合は切り上げ」...。
つまり、100.5円の場合は0.5を切り捨てて100円。100.6円であれば切り上げて101円ってこと? これは四捨五入じゃないような...
はっ!五捨六入...?
五捨六入
そこで「保険料、五捨六入」と調べると事例がたくさん出てきました。 Rubyでも五捨六入に相当するメソッドが用意されていますのでそれを使います。
BigDecimal("10.5").round(0, BigDecimal::ROUND_HALF_DOWN).to_f
=> 10.0
BigDecimal("10.6").round(0, BigDecimal::ROUND_HALF_DOWN).to_f
=> 11.0
これで実現できてそうです。
しかし、実は「五捨六入」という言葉は正しくありません。
なぜなら、「50銭以下の場合は切り捨て、50銭を超える場合は切り上げ」なので、0.5は切り捨てて、0.51は切り上げるのです。
つまり「六入」ではない、ということです。
もし、0.5から0.6の間の値が切り捨てられるようだと、その範囲の値の場合のみ1円単位の誤差が出てしまいます。
BigDecimal::ROUNDHALFDOWNの動作を確認してみましょう。
BigDecimal("10.51").round(0, BigDecimal::ROUND_HALF_DOWN).to_f
=> 11.0
BigDecimal("10.501").round(0, BigDecimal::ROUND_HALF_DOWN).to_f
=> 11.0
「六入」ではなく、0.5を「超える場合は切り上げ」になっているようです。
これで「50銭以下の場合は切り捨て、50銭を超える場合は切り上げ」が実現できていることが確認できました。
整数部の切り捨て
さて、もう少し協会けんぽの保険料額表を見てみましょう。
「賞与に係る保険料額は、賞与額から1,000円未満の端数を切り捨てた額(標準賞与額)に、保険料率を乗じた額となります。」とあります。
小数点以下の切り捨てではなく整数部での切り捨て...です。 これはroundの引数にマイナスの値を入れれば実現できます。
BigDecimal("1900").round(-3, BigDecimal::ROUND_FLOOR).to_f
=> 1000.0
ちなみに四捨五入の場合は、roundでも同様に整数部の指定ができます。
1500.round(-3)
=> 2000
エンジニア募集中!
ビジネスバンクグループではエンジニアを募集中しています。
弊社が採用しているテクノロジや開発環境に興味を持った方は、 ここから是非エントリー を!