Javaでは小数点以下の数値をdoubleやfloatのまま計算(四則演算)を行うと2進数で処理されるため、2進数で扱いきれない数値は丸め誤差が発生してしまいます。金額など誤差が許されない計算をJavaで実施する場合はBigDecimalを使用するべきです。
doubleやfloatで誤差が出る例
- 以下の様な計算をdoubleやfloatで実施すると丸め誤差が発生して正確な結果が得られません。
123456public static void main(String[] args) {double d = 1.3 + 2.1;float f = 1.3f + 2.1f;System.out.println("double = " + d);System.out.println("float = " + f);}
- コンソール
12double = 3.4000000000000004float = 3.3999999
BigDecimalで加算した場合の例
- 上記の誤差が発生した計算をBigDecimalで実施すると以下の様に誤差は発生しなくなります。
12345public static void main(String[] args) {BigDecimal bd = new BigDecimal("1.3");BigDecimal bdAdd = new BigDecimal("2.1").add(bd);System.out.println("BigDecimal.add = " + bdAdd);}
- コンソール
1BigDecimal.add = 3.4
BigDecimalで減算、乗算した場合の例
- BigDecimalで減算する場合はsubstractメソッド、乗算する場合はmultiplyメソッドを使用します。
1234567public static void main(String[] args) {BigDecimal bd = new BigDecimal("1.3");BigDecimal bdSub = new BigDecimal("1.1").subtract(bd); // 減算BigDecimal bdMul = new BigDecimal("1.1").multiply(bd); // 乗算System.out.println("BigDecimal.subtract = " + bdSub);System.out.println("BigDecimal.multiply = " + bdMul);}
- コンソール
12BigDecimal.subtract = -0.2BigDecimal.multiply = 1.43
BigDecimalで除算(四捨五入、切り捨て、切り上げ)した場合の例
- BigDecimalで除算する場合はdivideメソッドを使用し、第2引数へ取得したい小数部の桁数、第3引数へ第2引数へ指定した桁以降の扱い(RoundingMode.*)を指定します。
12345678public static void main(String[] args) {BigDecimal bdDiv = new BigDecimal("1.1").divide(bd,4,RoundingMode.HALF_UP); // 除算(小数部第4位まで表示、第5位は四捨五入)BigDecimal bdDivFloor = new BigDecimal("1.1").divide(bd,4,RoundingMode.FLOOR); // 除算(小数部第4位まで表示、第5位は切り捨て)BigDecimal bdDivCeiling = new BigDecimal("1.1").divide(bd,4,RoundingMode.CEILING); // 除算(小数部第4位まで表示、第5位は切り上げ)System.out.println("BigDecimal.divide(HALF_UP) = " + bdDiv);System.out.println("BigDecimal.divide(FLOOR) = " + bdDivFloor);System.out.println("BigDecimal.divide(CEILING) = " + bdDivCeiling);}
- コンソール
123BigDecimal.divide(HALF_UP) = 0.8462BigDecimal.divide(FLOOR) = 0.8461BigDecimal.divide(CEILING) = 0.8462
- RoundingModeの種類について
RoundingModeの列挙型定数 説明 RoundingMode.HALF_UP 四捨五入 RoundingMode.FLOOR 切り捨て(負の無限大に近づくように丸める) RoundingMode.DOWN 切り捨て(0に近づくように丸める) RoundingMode.CEILING 切り上げ RoundingMode.HALF_DOWN 五捨六入(もっとも近い数字に丸める) RoundingMode.HALF_EVEN 偶数の場合はHALF_DOWN、奇数の場合はHALF_UPのように動作します RoundingMode.UNNECESSARY 何もしない
※丸めが必要な場合はArithmeticExceptionをスローします