JavaでBigDecimalが必要な理由を理解するために、doubleやfloatでは問題が発生するケースを考えながら説明します。
1. double や float の誤差問題¶
doubleやfloatは**浮動小数点数(IEEE 754)**を使用しており、10進数を正確に表現できないため、計算時に誤差が発生します。
誤差の例¶
public class Main {
public static void main(String[] args) {
double a = 0.1;
double b = 0.2;
double c = a + b;
System.out.println("0.1 + 0.2 = " + c); // 期待: 0.3, 実際: 0.30000000000000004
}
}
出力
0.1 + 0.2 = 0.30000000000000004
このように、double では 誤差が発生するため、正確な計算が必要な場面(金融計算など)には適さない ことが分かります。
2. BigDecimal を使うと誤差が発生しない¶
BigDecimal は 任意精度の10進数演算をサポート するため、誤差のない計算が可能です。
BigDecimalを使用した例¶
import java.math.BigDecimal;
public class Main {
public static void main(String[] args) {
BigDecimal a = new BigDecimal("0.1");
BigDecimal b = new BigDecimal("0.2");
BigDecimal c = a.add(b);
System.out.println("0.1 + 0.2 = " + c); // 正確に 0.3 になる
}
}
出力
0.1 + 0.2 = 0.3
BigDecimal を使用すると、誤差のない計算が可能になります。
3. BigDecimal の用途¶
BigDecimal は以下のような用途で使用されます。
(1) 金融・会計計算¶
- お金の計算(銀行、税金、請求書など)
- 例えば、0.1円単位で計算が必要な場合、
doubleの誤差では問題になる -
BigDecimalなら 正確な桁数で管理できる
(2) 高精度の科学計算¶
- 天文学、物理シミュレーションなど で高精度が必要な場合
-
doubleの誤差が大きな影響を及ぼす計算ではBigDecimalを使う
(3) 数値フォーマットが重要な場面¶
- 税率、為替レート などの値を厳密に管理
-
doubleでは丸め誤差が発生するため、厳密な計算が必要
4. BigDecimal の注意点¶
(1) BigDecimal の生成には String を使う¶
BigDecimal x = new BigDecimal("0.1"); // 正確
BigDecimal y = new BigDecimal(0.1); // doubleの誤差がそのまま適用される(NG)
new BigDecimal(0.1) の場合、既に double の誤差が含まれてしまうため、必ず String を使って生成 するのがベスト。
(2) BigDecimal の演算方法¶
BigDecimal は + や * などの演算子が使えない ため、メソッドを使う必要があります。
| 操作 | メソッド | 例 |
|---|---|---|
| 加算 | add(BigDecimal) |
a.add(b) |
| 減算 | subtract(BigDecimal) |
a.subtract(b) |
| 乗算 | multiply(BigDecimal) |
a.multiply(b) |
| 除算 | divide(BigDecimal, RoundingMode) |
a.divide(b, RoundingMode.HALF_UP) |
| 比較 | compareTo(BigDecimal) |
a.compareTo(b) == 0 |
(3) BigDecimal の丸め¶
divide() を使う際、丸めモード(RoundingMode)を指定する必要 があります。
import java.math.BigDecimal;
import java.math.RoundingMode;
public class Main {
public static void main(String[] args) {
BigDecimal a = new BigDecimal("10");
BigDecimal b = new BigDecimal("3");
BigDecimal result = a.divide(b, 2, RoundingMode.HALF_UP); // 小数点以下2桁で四捨五入
System.out.println("10 / 3 = " + result);
}
}
出力
10 / 3 = 3.33
double のように 無限小数になってエラーになることを防ぐ ことができます。
5. まとめ¶
double |
BigDecimal |
|
|---|---|---|
| 精度 | 誤差が出る(10進数を正確に表現できない) | 任意精度で計算できる |
| 計算 |
+ - * / で直接演算可能 |
add() subtract() などのメソッドを使用 |
| 用途 | 高速な計算が必要な場面(例: グラフィック処理) | 金融計算、会計、正確な数値管理 |
| 丸め処理 |
Math.round() で対応 |
RoundingMode を使用 |
| 比較 |
== を使うと誤差で問題が出る |
compareTo() を使えば正確 |
6. BigDecimal を使うべきケース¶
✅ 金融計算(お金の計算)
✅ 精度が必要な科学計算
✅ 厳密な値の管理(税率、為替など)
🚀 一方で、double が適しているケースもある
- 大量の数値演算(例えば機械学習、物理エンジン)
- パフォーマンス重視のアプリ
BigDecimal は計算精度が高いが、計算速度は double より遅いため、適材適所で使い分けることが重要です!