0Pricing
Java Academy · レッスン

金額にdoubleを使わない理由

浮動小数点の精度問題を学びます

「金額にdoubleを使わない理由」はCoddyKit上の無料Java Academyレッスンです。 これはレッスン1/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはJava Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Java Academyコースには全4レッスンが含まれています。

危険なデフォルト

価格をdoubleに保存するのは自然に思えます。しかし、doubleではほとんどの小数を正確に表現できないため、金融計算を台無しにする小さな誤差が生じます。

典型的な驚き

doubleで0.1と0.2を足しても、0.3にはなりません。ごく小さな丸め誤差を含む値になります。

public class Main {
    public static void main(String[] args) {
        double result = 0.1 + 0.2;
        System.out.println(result);
    }
}

なぜ起こるのか

コンピューターはdoubleを2進数で保存します。3分の1を10進数で正確に表せないのと同じように、0.1のような多くの小数は2進数で正確に表せません。

最も近い2進数の近似値が保存されるため、誤差が蓄積します。

誤差は蓄積する

1回だけ発生するごく小さな誤差は無害に見えるかもしれません。しかし、何千件もの取引をループで処理すると、差が蓄積して目に見える間違いになります。

public class Main {
    public static void main(String[] args) {
        double total = 0.0;
        for (int i = 0; i < 10; i++) {
            total += 0.1;
        }
        System.out.println(total);
    }
}

等価比較の失敗

丸め誤差があるため、計算したdoubleを==で比較すると、等しいはずなのに一致しないことがよくあります。

public class Main {
    public static void main(String[] args) {
        double a = 0.1 + 0.2;
        double b = 0.3;
        System.out.println(a == b);
    }
}

金額には正確さが必要

金融分野では、1セント未満の誤差であっても許容できません。監査では合計が1セント単位まで一致することが求められます。

そのため、金額を浮動小数点型で保存してはいけません。

解決策:BigDecimal

Javaには、小数を正確に保存するクラスBigDecimalが用意されています。非スケールド値とスケールを別々に管理するため、0.1は本当に0.1を意味します。

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");
        System.out.println(a.add(b));
    }
}

Stringコンストラクターを必ず使用する

BigDecimalはdoubleではなくStringから作成してください。doubleを渡すと、2進数の誤差がBigDecimalに持ち込まれます。

import java.math.BigDecimal;

public class Main {
    public static void main(String[] args) {
        BigDecimal fromDouble = new BigDecimal(0.1);
        BigDecimal fromString = new BigDecimal("0.1");
        System.out.println(fromDouble);
        System.out.println(fromString);
    }
}

またはvalueOfを使用する

BigDecimal.valueOfは安全な簡略方法です。doubleを標準的な文字列表現に変換してから扱うため、元の2進数の誤差を避けられます。

import java.math.BigDecimal;

public class Main {
    public static void main(String[] args) {
        BigDecimal price = BigDecimal.valueOf(19.99);
        System.out.println(price);
    }
}

金額をセントで保存する

単純なケースでは、longを使って金額を整数のセント数として保存する方法もあります。すると19.99ドルは1999セントとなり、すべての計算を正確な整数演算で行えます。

public class Main {
    public static void main(String[] args) {
        long cents = 1999;
        long total = cents * 3;
        System.out.println(total + " cents");
    }
}

要点

小さな誤差が許容される科学計算やグラフィックスではfloatとdoubleを使用してください。金額や正確さが必要な値には、BigDecimalまたは整数のセント数を使用してください。

理解度チェック

浮動小数点の精度について、理解度を確認しましょう。

まとめ

doubleが金額の扱いに適さない理由について学びました。

  • 2進浮動小数点では多くの小数を正確に保存できない
  • 0.1 + 0.2が0.3と等しくならないような誤差が蓄積する
  • 正確な小数演算にはBigDecimalを使用する
  • Stringから作成するかvalueOfを使用し、生のdoubleからは決して作成しない
  • 整数のセント数で保存する方法もある

よくある質問

「金額にdoubleを使わない理由」レッスンは無料ですか?

はい。「金額にdoubleを使わない理由」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Java Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Java Academyコースには全4レッスンが含まれています。

「金額にdoubleを使わない理由」で何を学びますか?

浮動小数点の精度問題を学びます ブラウザで直接実行するハンズオンコードでJava Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

Java Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのJava Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン1/4です。

「金額にdoubleを使わない理由」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このJava Academyレッスンでコードを書いて実行できますか?

はい。すべてのJava Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. 金額にdoubleを使わない理由
  2. BigDecimalの操作
  3. 丸めとスケール
  4. 巨大な数値のためのBigInteger
← Java Academyに戻る