【Java入門 実用編】 BigDecimal クラスの利用(2)
2025.08.08
前回の記事では、BigDecimal クラスのインスタンスの生成や精度、スケール、四則演算や大小の比較などクラスの基本的な扱い方についてご紹介しました。当記事では、さらに累乗、平方根などの扱いのほか、BigDecimal クラスの利用時には特に必要とされることの多い、スケールと丸め処理およびそのモードについてご紹介します。
目次
- 1 累乗・平方根
- 2 10のN乗倍・小数点の移動
- 3 BigDecimal クラスの切り上げ・切り捨て・四捨五入
- 4 RoundingMode 毎の動作
- 4.1 RoundingMode.CEILING(BigDecimal.ROUND_CEILING)
- 4.2 RoundingMode.UP(BigDecimal.ROUND_UP)
- 4.3 RoundingMode.FLOOR(BigDecimal.ROUND_FLOOR)
- 4.4 RoundingMode.DOWN(BigDecimal.ROUND_DOWN)
- 4.5 RoundingMode.HALF_UP(BigDecimal.ROUND_HALF_UP)
- 4.6 RoundingMode.HALF_DOWN(BigDecimal.ROUND_HALF_DOWN)
- 4.7 RoundingMode.HALF_EVEN(BigDecimal.ROUND_HALF_EVEN)
- 4.8 RoundingMode.UNNECESSARY(BigDecimal.ROUND_UNNECESSARY)
- 4.9 MathContext で丸めモードを指定する例
累乗・平方根
累乗(pow メソッド)
pow メソッドは、BigDecimal の値のN乗(Nは引数)の値を持つ BigDecimal のインスタンスを返します。
pow メソッド - Java 21 APIドキュメント(java.math.BigDecimal)
引数は int 値(整数値)ですが、0以上の値である必要があります。負の値を引数に指定した場合は ArithmeticException がスローされます。
BigDecimal bd = BigDecimal.valueOf(2);
// 4(2の2乗)
System.out.println(bd.pow(2));
// 1024(2の10乗)
System.out.println(bd.pow(10));
平方根(sqrt メソッド)※java9以降
sqrt メソッドは、BigDecimal の平方根を返します。平方根は無理数となる場合があるため、引数に java.math.MathContext クラスのインスタンスを渡して、平方根の精度(有効桁数)と丸めモードを指定する必要があります。
sqrt メソッド - Java 21 APIドキュメント(java.math.BigDecimal)
sqrt メソッドを呼び出す BigDecimal の値は正の値またはゼロである必要があります。負の値を持つ BigDecimal インスタンスから呼び出した場合は ArithmeticException がスローされます。
また、引数で指定した精度よりも小さな精度で割り切れる場合は、返却値の精度はその桁数に縮小されます。
BigDecimal bd1 = BigDecimal.valueOf(2);
BigDecimal bd2 = BigDecimal.valueOf(0.0004);
// 1.41421356(精度:9)
System.out.println(bd1.sqrt(new MathContext(9, RoundingMode.HALF_UP)));
// 0.02(割り切れるため精度は縮小)
System.out.println(bd2.sqrt(new MathContext(9, RoundingMode.HALF_UP)));
10のN乗倍・小数点の移動
10のN乗倍(scaleByPowerOfTen メソッド)
scaleByPowerOfTen メソッドは、元の BigDecimal に10 のN乗(N = 引数)を乗じた値の BigDecimal インスタンスを返します。
scaleByPowerOfTen メソッド - Java 21 APIドキュメント(java.math.BigDecimal)
scaleByPowerOfTen メソッドの引数は pow メソッドと同じく int 値(整数値)ですが、scaleByPowerOfTen メソッドでは負の値も設定可能です。負の値(-N)を設定した場合は、元の BigDecimal に「10 のN乗分の 1」を乗じた値の BigDecimal インスタンスを返します。
また、戻り値の精度はメソッド呼び出し元の精度と同じ精度のままとなります。これは、10のN乗倍であるため必ず同じ精度で表現できるためです。
BigDecimal bd = BigDecimal.valueOf(20);
// 10の1乗を乗じる(20 x 10 = 200)→ 出力: 2.0E+2
System.out.println(bd.scaleByPowerOfTen(1));
// 10の4乗を乗じる(20 x 10000 = 200000)→ 出力: 2.0E+5
System.out.println(bd.scaleByPowerOfTen(4));
// 10のマイナス2乗を乗じる(20 x (1 / 100) = 0.20)→ 出力: 0.20
System.out.println(bd.scaleByPowerOfTen(-2));
小数点の移動
小数点を左に移動(movePointLeft メソッド)
movePointLeft メソッドは、引数で指定した数だけ左へ動かします。
movePointLeft メソッド - Java 21 APIドキュメント(java.math.BigDecimal)
引数は int 値で移動させる桁数を指定します。負の値を指定した場合は小数点は逆(右)へ動きます。また、0 を指定した場合はメソッドを呼び出したインスタンスをそのまま返却します。
scaleByPowerOfTen メソッドと異なり、movePointLeft メソッドでは精度は必要に応じて拡張されます。(縮小はされません)
BigDecimal bd = BigDecimal.valueOf(20);
// 小数点を左へ1つ移動=10の1乗で除する(20 ÷ 10 = 2)→ 出力: 2.0
System.out.println(bd.movePointLeft(1));
// 小数点を左へ4つ移動=10の4乗で除する(20 ÷ 10000 = 0.002)→ 出力: 0.0020
System.out.println(bd.movePointLeft(4));
// 引数が負の値の場合は小数点を逆に(右に)移動=10の2乗を乗じる(20 x 100 = 2000)→ 出力: 2000
System.out.println(bd.movePointLeft(-2));
小数点を右に移動(movePointRight メソッド)
movePointLeft メソッドは、引数で指定した数だけ左へ動かします。
movePointRight メソッド - Java 21 APIドキュメント(java.math.BigDecimal)
引数は int 値で移動させる桁数を指定します。負の値を指定した場合は小数点は逆(左)へ動きます。また、0 を指定した場合はメソッドを呼び出したインスタンスをそのまま返却します。
こちらも scaleByPowerOfTen メソッドと異なり、精度は必要に応じて拡張されます。(縮小はされません)
BigDecimal bd = BigDecimal.valueOf(20);
// 小数点を右へ1つ移動=10の1乗を乗じる(20 x 10 = 200)→ 出力: 200
System.out.println(bd.movePointRight(1));
// 小数点を右へ4つ移動=10の4乗を乗じる(20 x 10000 = 200000)→ 出力: 200000
System.out.println(bd.movePointRight(4));
// 引数が負の値の場合は小数点を逆に(左に)移動=10の2乗で除する(20 ÷ 100 = 0.2)→ 出力: 0.20
System.out.println(bd.movePointRight(-2));
BigDecimal クラスの切り上げ・切り捨て・四捨五入
スケールの変更(setScale メソッド)
setScale メソッドは、BigDecimal の値を指定したスケール(小数点以下の桁数)とした BigDecimal インスタンスを返します。
setScale メソッド - Java 21 APIドキュメント(java.math.BigDecimal)
指定した桁数よりも小さい桁の範囲にゼロ以外の値がある場合は、引数の RoundingMode の値( Java 8 までは第2引数の int 値)によって丸め(切り上げ、切り捨てなど)の動作を指定する必要があります。指定をしない場合は ArithmeticException が発生します。
RoundingMode の種類と動作については、後述の「RoundingMode 毎の動作」をご確認ください。
BigDecimal bd = BigDecimal.valueOf(123456.789);
// スケール:3
System.out.println(bd.scale());
// 123456.789000 (スケールを3から6に変更。拡大したスケールの部分はゼロ埋め)
System.out.println(bd.setScale(6));
// 123456.7(丸めモードをDOWNに指定してスケールを3から1に縮小)
System.out.println(bd.setScale(1, RoundingMode.DOWN));
// これはArithmeticExceptionが発生する
// (指定したスケールより小さい値の丸めモードを指定する必要がある)
System.out.println(bd.setScale(1));
// この場合はOK(指定したスケール以下にはゼロしかないため)
BigDecimal bd2 = BigDecimal.valueOf(123456.700);
System.out.println(bd.setScale(1));
精度の変更(縮小)(round メソッド)
round メソッドでは、BigDecimal の精度を変更(縮小)することができます。
round メソッド - Java 21 APIドキュメント(java.math.BigDecimal)
引数の MathContext で指定した精度が、元のBigDecimal インスタンスの精度よりも大きい、または等しい場合、元のインスタンスが返されます。精度を小さくする場合は、指定した精度より小さい値は MathContext クラスの RoundingMode の値に従って丸められます。
BigDecimal bd = BigDecimal.valueOf(123456.789);
// 精度:9
System.out.println("精度:" + bd.precision() );
// 精度;12 丸めモード:切り捨て
MathContext mc1 = new MathContext(12, RoundingMode.FLOOR);
// 123456.789(指定した精度が大きいため元の値が返される)
System.out.println(bd.round(mc1));
// 精度;5 丸めモード:切り捨て
MathContext mc2 = new MathContext(5, RoundingMode.FLOOR);
// 1.2345E+5(6桁目以降は切り捨て)
System.out.println(bd.round(mc2));
BigDecimal と RoundingModeについて
Java 8 までのBigDecimal クラスでは、setScale メソッドおよび divide メソッド(除算)の実行時に、返却値の小数点以下の桁数を指定する場合、指定した桁よりも小さい値をどのように扱う(丸める)かの方式を、BigDecimal クラス内の定数(int 値)で指定する必要がありました。
BigDecimal bd = BigDecimal.valueOf(12.3456);
// Java 8 までの方式(丸めを指定時)
BigDecimal bdHalfUp2 = bd.setScale(2, BigDecimal.ROUND_HALF_UP);
// 第二引数はintなので、以下のコードでも同じように動作する
BigDecimal bdHalfUp2 = bd.setScale(2, 4);
しかしながら、引数が int 型の場合、定数以外の値を指定したり、int 値のリテラルを直接コード上に記述してマジックナンバーとなってしまう懸念がありました。このため、java 9 以降ではスケールを指定する場合、丸めの方式は java.math.RoundingMode 列挙型の値を指定するように変更されています。(互換性のため int 型で指定するメソッドは残っていますが非推奨となっています)
BigDecimal bd = BigDecimal.valueOf(12.3456);
// Java 9 以降の方式(丸めを指定時)
BigDecimal bdHalfUp2 = bd.setScale(2, RoundingMode.HALF_UP);
// int,int を引数とするメソッドは残っているが非推奨
BigDecimal bdHalfUp2 = bd.setScale(2, BigDecimal.ROUND_HALF_UP);
RoundingMode 毎の動作
次に、RoundingMode の値ごとに、それぞれの丸め処理の動作の内容をご紹介します。これは、setScale メソッドおよび divide メソッドで直接指定する場合のほかに、MathContext クラスを利用する際に精度と丸め方式を指定する場合も同様の動作となります。
※カッコ内はそれぞれの丸めモードに対応する BigDecimal クラス内の定数(int値)
RoundingMode.CEILING
(BigDecimal.ROUND_CEILING)
RoundingMode.CEILING は、正の無限大に近づくように丸めるモードです。一般的な「切り上げ」の動作であり、負の値の場合は絶対値が小さくなる方向に丸められます(-9.9 は -9 に丸められる)。
CEILING - Java 21 APIドキュメント(java.math.RoundingMode)
// -9.9 -> -9 に丸められる
System.out.println(BigDecimal.valueOf(-9.9).setScale(0, RoundingMode.CEILING));
// -5.5 -> -5 に丸められる
System.out.println(BigDecimal.valueOf(-5.5).setScale(0, RoundingMode.CEILING));
// -4.5 -> -4 に丸められる
System.out.println(BigDecimal.valueOf(-4.5).setScale(0, RoundingMode.CEILING));
// -0.1 -> 0 に丸められる
System.out.println(BigDecimal.valueOf(-0.1).setScale(0, RoundingMode.CEILING));
// 0.0 -> 0 に丸められる
System.out.println(BigDecimal.valueOf(0.0).setScale(0, RoundingMode.CEILING));
// 0.1 -> 1 に丸められる
System.out.println(BigDecimal.valueOf(0.1).setScale(0, RoundingMode.CEILING));
// 4.5 -> 5 に丸められる
System.out.println(BigDecimal.valueOf(4.5).setScale(0, RoundingMode.CEILING));
// 5.5 -> 6 に丸められる
System.out.println(BigDecimal.valueOf(5.5).setScale(0, RoundingMode.CEILING));
// 9.9 -> 10 に丸められる
System.out.println(BigDecimal.valueOf(9.9).setScale(0, RoundingMode.CEILING));
RoundingMode.UP
(BigDecimal.ROUND_UP)
RoundingMode.UP は、0 から離れるように丸めるモードです。正の値の場合は RoundingMode.CEILING と同じ動作ですが、負の値の場合も絶対値が大きくなる方向に丸められる(-9.9 は -10 に丸められる)点が異なることに注意してください。
UP - Java 21 APIドキュメント(java.math.RoundingMode)
// -9.9 -> -10 に丸められる
System.out.println(BigDecimal.valueOf(-9.9).setScale(0, RoundingMode.UP));
// -5.5 -> -6 に丸められる
System.out.println(BigDecimal.valueOf(-5.5).setScale(0, RoundingMode.UP));
// -4.5 -> -5 に丸められる
System.out.println(BigDecimal.valueOf(-4.5).setScale(0, RoundingMode.UP));
// -0.1 -> -1 に丸められる
System.out.println(BigDecimal.valueOf(-0.1).setScale(0, RoundingMode.UP));
// 0.0 -> 0 に丸められる
System.out.println(BigDecimal.valueOf(0.0).setScale(0, RoundingMode.UP));
// 0.1 -> 1 に丸められる
System.out.println(BigDecimal.valueOf(0.1).setScale(0, RoundingMode.UP));
// 4.5 -> 5 に丸められる
System.out.println(BigDecimal.valueOf(4.5).setScale(0, RoundingMode.UP));
// 5.5 -> 6 に丸められる
System.out.println(BigDecimal.valueOf(5.5).setScale(0, RoundingMode.UP));
// 9.9 -> 10 に丸められる
System.out.println(BigDecimal.valueOf(9.9).setScale(0, RoundingMode.UP));
RoundingMode.FLOOR
(BigDecimal.ROUND_FLOOR)
RoundingMode.FLOOR は、負の無限大に近づくように丸めるモードです。一般的な「切り捨て」のの動作あり、負の値の場合は絶対値が小さくなる方向に丸められます(-9.9 は -10 に丸められる)。
FLOOR - Java 21 APIドキュメント(java.math.RoundingMode)
// -9.9 -> -10 に丸められる
System.out.println(BigDecimal.valueOf(-9.9).setScale(0, RoundingMode.FLOOR));
// -5.5 -> -6 に丸められる
System.out.println(BigDecimal.valueOf(-5.5).setScale(0, RoundingMode.FLOOR));
// -4.5 -> -5 に丸められる
System.out.println(BigDecimal.valueOf(-4.5).setScale(0, RoundingMode.FLOOR));
// -0.1 -> -1 に丸められる
System.out.println(BigDecimal.valueOf(-0.1).setScale(0, RoundingMode.FLOOR));
// 0.0 -> 0 に丸められる
System.out.println(BigDecimal.valueOf(0.0).setScale(0, RoundingMode.FLOOR));
// 0.1 -> 0 に丸められる
System.out.println(BigDecimal.valueOf(0.1).setScale(0, RoundingMode.FLOOR));
// 4.5 -> 4 に丸められる
System.out.println(BigDecimal.valueOf(4.5).setScale(0, RoundingMode.FLOOR));
// 5.5 -> 5 に丸められる
System.out.println(BigDecimal.valueOf(5.5).setScale(0, RoundingMode.FLOOR));
// 9.9 -> 9 に丸められる
System.out.println(BigDecimal.valueOf(9.9).setScale(0, RoundingMode.FLOOR));
RoundingMode.DOWN
(BigDecimal.ROUND_DOWN)
RoundingMode.DOWN は、0 に近づくように丸めるモードです。正の値の場合は RoundingMode.FLOOR と同じ動作ですが、負の値の場合も絶対値が小さくなる方向に丸められる(-9.9 は -9 に丸められる)点が異なることに注意してください。
DOWN - Java 21 APIドキュメント(java.math.RoundingMode)
// -9.9 -> -9 に丸められる
System.out.println(BigDecimal.valueOf(-9.9).setScale(0, RoundingMode.DOWN));
// -5.5 -> -5 に丸められる
System.out.println(BigDecimal.valueOf(-5.5).setScale(0, RoundingMode.DOWN));
// -4.5 -> -4 に丸められる
System.out.println(BigDecimal.valueOf(-4.5).setScale(0, RoundingMode.DOWN));
// -0.1 -> 0 に丸められる
System.out.println(BigDecimal.valueOf(-0.1).setScale(0, RoundingMode.DOWN));
// 0.0 -> 0 に丸められる
System.out.println(BigDecimal.valueOf(0.0).setScale(0, RoundingMode.DOWN));
// 0.1 -> 0 に丸められる
System.out.println(BigDecimal.valueOf(0.1).setScale(0, RoundingMode.DOWN));
// 4.5 -> 4 に丸められる
System.out.println(BigDecimal.valueOf(4.5).setScale(0, RoundingMode.DOWN));
// 5.5 -> 5 に丸められる
System.out.println(BigDecimal.valueOf(5.5).setScale(0, RoundingMode.DOWN));
// 9.9 -> 9 に丸められる
System.out.println(BigDecimal.valueOf(9.9).setScale(0, RoundingMode.DOWN));
RoundingMode.HALF_UP
(BigDecimal.ROUND_HALF_UP)
RoundingMode.HALF_UP は、指定された桁数で最も近い数字に丸めるモードです。但し、2つの数字から同じだけ離れている(『1 と 2 の間の 1.5』や『0.2 と 0.3 の間の 0.25』 などの)場合は、0 から離れるように丸められます。
HALF_UP - Java 21 APIドキュメント(java.math.RoundingMode)
// -9.9 -> -10 に丸められる
System.out.println(BigDecimal.valueOf(-9.9).setScale(0, RoundingMode.HALF_UP));
// -5.5 -> -6 に丸められる
System.out.println(BigDecimal.valueOf(-5.51).setScale(0, RoundingMode.HALF_UP));
// -4.5 -> -5 に丸められる
System.out.println(BigDecimal.valueOf(-4.5).setScale(0, RoundingMode.HALF_UP));
// -0.1 -> 0 に丸められる
System.out.println(BigDecimal.valueOf(-0.1).setScale(0, RoundingMode.HALF_UP));
// 0.0 -> 0 に丸められる
System.out.println(BigDecimal.valueOf(0.0).setScale(0, RoundingMode.HALF_UP));
// 0.1 -> 0 に丸められる
System.out.println(BigDecimal.valueOf(0.1).setScale(0, RoundingMode.HALF_UP));
// 4.5 -> 5 に丸められる
System.out.println(BigDecimal.valueOf(4.5).setScale(0, RoundingMode.HALF_UP));
// 5.5 -> 6 に丸められる
System.out.println(BigDecimal.valueOf(5.5).setScale(0, RoundingMode.HALF_UP));
// 9.9 -> 10 に丸められる
System.out.println(BigDecimal.valueOf(9.9).setScale(0, RoundingMode.HALF_UP));
RoundingMode.HALF_DOWN
(BigDecimal.ROUND_HALF_DOWN)
RoundingMode.HALF_UP は、指定された桁数で最も近い数字に丸めるモードです。但し、2つの数字から同じだけ離れている(『1 と 2 の間の 1.5』や『0.2 と 0.3 の間の 0.25』 などの)場合は、0 に近づくように丸められます。
HALF_DOWN - Java 21 APIドキュメント(java.math.RoundingMode)
// -9.9 -> -10 に丸められる
System.out.println(BigDecimal.valueOf(-9.9).setScale(0, RoundingMode.HALF_DOWN));
// -5.51 -> -6 に丸められる
System.out.println(BigDecimal.valueOf(-5.51).setScale(0, RoundingMode.HALF_DOWN));
// -5.5 -> -5 に丸められる
System.out.println(BigDecimal.valueOf(-5.5).setScale(0, RoundingMode.HALF_DOWN));
// -4.5 -> -4 に丸められる
System.out.println(BigDecimal.valueOf(-4.5).setScale(0, RoundingMode.HALF_DOWN));
// -0.1 -> 0 に丸められる
System.out.println(BigDecimal.valueOf(-0.1).setScale(0, RoundingMode.HALF_DOWN));
// 0.0 -> 0 に丸められる
System.out.println(BigDecimal.valueOf(0.0).setScale(0, RoundingMode.HALF_DOWN));
// 0.1 -> 0 に丸められる
System.out.println(BigDecimal.valueOf(0.1).setScale(0, RoundingMode.HALF_DOWN));
// 4.5 -> 4 に丸められる
System.out.println(BigDecimal.valueOf(4.5).setScale(0, RoundingMode.HALF_DOWN));
// 5.5 -> 5 に丸められる
System.out.println(BigDecimal.valueOf(5.5).setScale(0, RoundingMode.HALF_DOWN));
// 5.51 -> 6 に丸められる
System.out.println(BigDecimal.valueOf(5.51).setScale(0, RoundingMode.HALF_DOWN));
// 9.9 -> 10 に丸められる
System.out.println(BigDecimal.valueOf(9.9).setScale(0, RoundingMode.HALF_DOWN));
RoundingMode.HALF_EVEN
(BigDecimal.ROUND_HALF_EVEN)
RoundingMode.HALF_EVEN は、指定された桁数で最も近い数字に丸めるモードです。但し、2つの数字から同じだけ離れている(『1 と 2 の間の 1.5』や『0.2 と 0.3 の間の 0.25』 などの)場合は、指定した最後の桁が最も近い偶数になるように丸められます。
HALF_EVEN - Java 21 APIドキュメント(java.math.RoundingMode)
この丸め方式は、「偶数への丸め」「銀行丸め」などとも呼ばれ、統計的な偏りを減らす効果があるため、IEEE 754などの標準規格でも推奨されています。また余談ですが、.NETなどの言語ではこの丸め方式がデフォルトで採用されています。
// -9.9 -> -10 に丸められる
System.out.println(BigDecimal.valueOf(-9.9).setScale(0, RoundingMode.HALF_EVEN));
// -5.5 -> -6 に丸められる
System.out.println(BigDecimal.valueOf(-5.5).setScale(0, RoundingMode.HALF_EVEN));
// -4.5 -> -4 に丸められる
System.out.println(BigDecimal.valueOf(-4.5).setScale(0, RoundingMode.HALF_EVEN));
// -0.1 -> 0 に丸められる
System.out.println(BigDecimal.valueOf(-0.1).setScale(0, RoundingMode.HALF_EVEN));
// 0.0 -> 0 に丸められる
System.out.println(BigDecimal.valueOf(0.0).setScale(0, RoundingMode.HALF_EVEN));
// 0.1 -> 0 に丸められる
System.out.println(BigDecimal.valueOf(0.1).setScale(0, RoundingMode.HALF_EVEN));
// 4.5 -> 4 に丸められる
System.out.println(BigDecimal.valueOf(4.5).setScale(0, RoundingMode.HALF_EVEN));
// 5.5 -> 6 に丸められる
System.out.println(BigDecimal.valueOf(5.5).setScale(0, RoundingMode.HALF_EVEN));
// 9.9 -> 10 に丸められる
System.out.println(BigDecimal.valueOf(9.9).setScale(0, RoundingMode.HALF_EVEN));
RoundingMode.UNNECESSARY
(BigDecimal.ROUND_UNNECESSARY)
RoundingMode.UNNECESSARY は、丸めを必要としないことを示すモードです。このモードを指定して計算を行った際、丸めが必要な桁数以下の値が含まれていた場合は、ArithmeticException がスローされます。ただし、丸めが必要ではなくてもスケールが異なる場合は、指定したスケールの値が返されます。
UNNECESSARY - Java 21 APIドキュメント(java.math.RoundingMode)
RoundingMode.UNNECESSARY は丸め処理を行うためには利用できませんが、BigDecimal の値が指定の桁数内に丸め済みであるかどうかのチェックに利用することができます。
// 10 のまま(丸め不要、スケールも変更なし)
System.out.println(BigDecimal.valueOf(10).setScale(0, RoundingMode.UNNECESSARY));
// 10.0 となる(丸めは不要だが、スケールは 2 から 1 に変更)
System.out.println(BigDecimal.valueOf(10.00).setScale(1, RoundingMode.UNNECESSARY));
// ArithmeticException が発生(スケールが 1 だが小数点以下第二位に丸め対象あり)
System.out.println(BigDecimal.valueOf(10.05).setScale(1, RoundingMode.UNNECESSARY));
MathContext で丸めモードを指定する例
BigDecimal クラスでは、コンストラクタや四則演算などのメソッドの実行時に、MathContext に RoundingMode を設定して引数として渡すことで、戻り値の BigDecimal インスタンスの精度と丸めモードを指定することができます。ここでは、メソッドで MathContext を引数に渡して利用するパターンについて例示します。
MathContext クラスのコンストラクタ
MathContext クラス のコンストラクタは、精度のみ、精度+丸めモード、文字列(精度と丸めモードを表す文字列)の3通りがあります。
精度のみ指定する場合は、丸めモードはデフォルト(RoundingMode.HALF_UP)となります。また、文字列で精度と丸めモードを指定する場合は「precision=NN roundingMode=NAME」(NNは精度、NAMEはRoundingMode名)の形式である必要があります。
通常は文字列で指定するケースはあまりないと思われますが、既存の MathContext インスタンスと同じ内容で作成したい場合に、toStringメソッドを利用してコピーすることができます。
// 精度のみ指定(丸めモードはデフォルト/RoundingMode.HALF_UP)
MathContext mc10 = new MathContext(10);
// 精度と丸めモードを指定
MathContext mc5Floor = new MathContext(5, RoundingMode.FLOOR);
// 文字列で精度と丸めモードを指定(文字列は必ずこの形式である必要がある)
MathContext mcByString = new MathContext("precision=5 roundingMode=FLOOR");
// toString メソッドを利用して同じ内容のインスタンスを作成
MathContext mcCopy = new MathContext(mc5Floor.toString());
MathContext クラスを利用することで、 BigDecimal クラスではコンストラクタをはじめ、四則演算(add、subtract、multiply、divide)、平方根(sqrt)、丸め(round)、絶対値(abs)など様々なメソッドで戻り値の精度と丸めモードを指定できます。
例1)sqrt メソッド
平方根を取得する sqrt メソッドでは、割り切れない値となるケースがあるため精度を指定する必要がありますが、最後の1桁に対してどのような丸め処理を行うかを指定できます。
BigDecimal bd = BigDecimal.valueOf(2);
MathContext mc5Floor = new MathContext(5, RoundingMode.FLOOR);
MathContext mc5Ceiling = new MathContext(5, RoundingMode.CEILING);
// 2 の平方根は 1.41421356...
// 1.4142(以降の桁は切り捨て)
System.out.println(bd.sqrt(mc5Floor));
// 1.4143(以降の桁を切り上げ)
System.out.println(bd.sqrt(mc5Ceiling));
例2)divide メソッド
除算を行う divide メソッドは、スケールや丸めモードを直接指定する引数の他に、MathContext を引数とするオーバーロードも準備されています。ただしこの2つは「スケール(小数点以下の桁数)」と「精度(有効な桁数)」丸めの基準となる概念が異なるため注意が必要です。
BigDecimal bd = BigDecimal.valueOf(1000);
BigDecimal divider = BigDecimal.valueOf(7);
MathContext mc10Floor = new MathContext(10, RoundingMode.FLOOR);
MathContext mc10Ceiling = new MathContext(10, RoundingMode.CEILING);
/* スケールと丸めモードを指定 */
// 小数点以下10桁に切り捨てて丸め(142.857142857142... → 142.8571428571)
System.out.println( bd.divide(divider, 10, RoundingMode.FLOOR));
// 小数点以下10桁に切り上げて丸め(142.857142857142... → 142.8571428572)
System.out.println( bd.divide(divider, 10, RoundingMode.CEILING));
/* MathContextで精度と丸めモードを指定 */
// 有効数字10桁で切り捨てて丸め(142.857142857142... → 142.8571428)
System.out.println( bd.divide(divider, mc10Floor));
// 有効数字10桁で切り上げて丸め(142.857142857142... → 142.8571429)
System.out.println( bd.divide(divider, mc10Ceiling));