MENU

【Java】BigDecimalの丸め処理にROUND系メソッドを使ってはいけない

こんにちは、くまごろーです。
今回はBigDecimalの丸め処理についてまとめます。
 
 
 
1 タイトルの意味
 
BigDecimalには数値を四捨五入・切上げ・切捨てするためのメソッドが用意されてます。
で、「BigDecimal 四捨五入」とかで検索すると、大体の記事は下記の様なROUND系メソッドを使用しています。

BigDecimal a = new BigDecimal("8");
BigDecimal b = new BigDecimal("6");
BigDecimal ans = a.divide(b, 2, BigDecimal.ROUND_HALF_UP);

でもこのROUND系メソッド、実はJava9からDeprecated(非推奨)になっているらしい・・・というわけで、Java8以前のバージョンを使用していない場合は、ROUND系メソッドは使うべきじゃないんです。
私も、STSさんに指摘されるまでは気づきませんでした。なのに、検索して上位に出てくる記事は軒並みROUND系メソッドを紹介しているという(-"-)
 
 
 
2 じゃあどうすればいいのか?
 
ROUND系メソッドではなく、java.math.RoundingModeクラスを使用します。RoundingModeはenum型で列挙されていて、以下の様な列挙型定数を持っています。

定数 説明
CEILING 正の無限大に近づくように丸める
DOWN 0に近づくよう丸める
FLOOR 負の無限大に近づくように丸める
HALF_DOWN 「もっとも近い数字」に丸める(5までは切り捨て、6以上は切り上げ)
HALF_EVEN 「もっとも近い数字」に丸める(両隣りの数字が等距離の場合は偶数側に丸める ※)
HALF_UP 「もっとも近い数字」に丸める丸めモードです(四捨五入)
UP 0から離れるように丸める(切り上げ)
UNNECESSARY 要求される演算の結果が正確であり、丸めが必要でないことを表す丸めモード

※ HALF_EVENについて
こういうことみたい。

BigDecimal a = new BigDecimal(number);
BigDecimal b = a.setScale(0, RoundingMode.HALF_UP);
//number = 6.1 -> 6
//number = 6.5 -> 6
//number = 6.6 -> 7
//number = 7.5 -> 8
//number = 7.6 -> 8


RoundingModeで冒頭のコードを書き直すと、こんな感じに。

BigDecimal a = new BigDecimal("8");
BigDecimal b = new BigDecimal("6");
BigDecimal ans = a.divide(b, 2, RoundingMode.HALF_UP);

 


3 結論
 
言語のバージョンが更新されると、このようなことが起きるんだなというのを実感しました。数か月間何も知らずROUND系メソッドを使用していたこと反省。
そして、やっぱり公式ドキュメントを確認するのは大事だなと身をもって体験しました・・・(-_-;) 
 
 

4 参考