java.text.NumberFormat
を使用して小数点を丸める時のデフォルト動作と、デフォルト動作の変更方法を紹介します。
JDKバージョン
$ java -version
java version "1.8.0_121"
Java(TM) SE Runtime Environment (build 1.8.0_121-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.121-b13, mixed mode)
デフォルトの動作
NumberFormat
のsetMaximumFractionDigits
メソッドに0
を指定すると、小数点を丸めることができます。
package com.example;
import java.text.NumberFormat;
import org.junit.Test;
public class NumberFormatTests {
@Test
public void testForDefault() {
NumberFormat numberFormat = NumberFormat.getInstance();
numberFormat.setMaximumFractionDigits(0); // 小数点の最大桁数を0に設定する
System.out.println(numberFormat.format(98.5));
System.out.println(numberFormat.format(99.5));
}
}
このコードを実行すると・・・
98
100
になります。おや???と思った方もいるのではないでしょうか?直感的には・・・
- 切り捨て
98
99
や
- 四捨五入?
99
100
などになることを期待しそう・・・。
で・・・この動作になるのは、NumberFormat
で管理しているRoundingMode
のデフォルト値がHALF_EVEN
のためです。
HALF_EVEN
のJavaDocを見てみると、『「もっとも近い数字」に丸める丸めモードです(ただし、両隣りの数字が等距離の場合は偶数側に丸めます)。』とあるため、「98.5」は「99」(奇数)ではなく「98」(偶数)へ、「99.5」は「99」(奇数)ではなく「100」(偶数)へ丸められたわけです。
RoundingMode
の変更
NumberFormat
のRoundingMode
は、setRoundingMode
メソッドで変更することができます。
@Test
public void testForRoundingModeIsDown() {
NumberFormat numberFormat = NumberFormat.getInstance();
numberFormat.setMaximumFractionDigits(0);
numberFormat.setRoundingMode(RoundingMode.DOWN); // RoundingModeを変更
System.out.println(numberFormat.format(98.5));
System.out.println(numberFormat.format(99.5));
}
このコードを実行すると・・・
98
99
になります。
まとめ
へ〜って感じですね。ぶっちゃけ自分もデフォルトの動作がHALF_EVEN
という部分は意識していませんでしたが、勉強になりました ちなみに・・・このエントリーを書いたきっかけは・・・ThymeleafのIssue(gh-581)です。Thymeleafつかって丸め処理を行うと、想定外の結果になっちゃうかもしれませんね(ざっと見た感じだと、
RoundingMode
を変更する手段はなさげだったので)。