Java | 浮動小数点数の丸め誤差(限界)

Java Java
スポンサーリンク

浮動小数点数の丸め誤差(限界) について解説します。これは実際にプログラムを書いていくと必ず出会う落とし穴です。


1. 丸め誤差とは?

コンピュータは数値を 2進数(0と1) で表現します。
ところが、10進数で「きれいに表せる数」でも、2進数では無限に続いてしまう場合があります。

例:

  • 10進数の 0.1 は、2進数では 無限小数 になる
  • コンピュータは有限の桁数しか扱えないので、途中で切り捨てて保存する
    → これが 丸め誤差 です。

2. 実際の例題

例1: 0.1 を足していく

class Example7 {
    public static void main(String[] args) {
        double x = 0.1 + 0.1 + 0.1;
        System.out.println(x);
    }
}
Java

👉 出力: 0.30000000000000004
本当は 0.3 になるはずが、誤差が出ています。


例2: 比較の落とし穴

class Example8 {
    public static void main(String[] args) {
        double a = 0.1 * 3;
        double b = 0.3;
        System.out.println(a == b);
    }
}
Java

👉 出力: false
0.1 * 30.3 は理論上同じはずですが、内部表現の誤差で一致しません。


3. 誤差への対処法

  • 比較するときは「許容範囲」を決める
double a = 0.1 * 3;
double b = 0.3;
double epsilon = 1e-9; // 許容誤差

if (Math.abs(a - b) < epsilon) {
    System.out.println("ほぼ等しい");
}
Java

👉 誤差を考慮して「ほぼ等しい」と判定する。

  • お金の計算など正確さが必要な場合は BigDecimal を使う
import java.math.BigDecimal;

class Example9 {
    public static void main(String[] args) {
        BigDecimal a = new BigDecimal("0.1");
        BigDecimal b = a.multiply(new BigDecimal("3"));
        System.out.println(b); // 0.3
    }
}
Java

👉 BigDecimal は文字列ベースで計算するので誤差が出ない。


まとめ

  • 浮動小数点数は 内部的に近似値 で表現されるため、誤差が出ることがある
  • == で直接比較するのは危険
  • 誤差を許容するか、正確さが必要なら BigDecimal を使う

タイトルとURLをコピーしました