「駑馬十駕」を信念に IT系情報を中心に調べた事をコツコツ綴っています。

Javaでは小数点以下の数値をdoubleやfloatのまま計算(四則演算)を行うと2進数で処理されるため、2進数で扱いきれない数値は丸め誤差が発生してしまいます。金額など誤差が許されない計算をJavaで実施する場合はBigDecimalを使用するべきです。

doubleやfloatで誤差が出る例

  • 以下の様な計算をdoubleやfloatで実施すると丸め誤差が発生して正確な結果が得られません。
  • コンソール

BigDecimalで加算した場合の例

  • 上記の誤差が発生した計算をBigDecimalで実施すると以下の様に誤差は発生しなくなります。
  • コンソール

BigDecimalで減算、乗算した場合の例

  • BigDecimalで減算する場合はsubstractメソッド、乗算する場合はmultiplyメソッドを使用します。
  • コンソール

BigDecimalで除算(四捨五入、切り捨て、切り上げ)した場合の例

  • BigDecimalで除算する場合はdivideメソッドを使用し、第2引数へ取得したい小数部の桁数、第3引数へ第2引数へ指定した桁以降の扱い(RoundingMode.*)を指定します。
  • コンソール
  • 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をスローします

補足:注意すべきポイントとベストプラクティス

本稿では BigDecimal を使って浮動小数点による丸め誤差を回避する基本的な使い方をご紹介しましたが、実務で使う際には以下の点にもご留意ください。

  1. 文字列コンストラクタを使う理由
    new BigDecimal("1.3") のように文字列引数を用いるのは、new BigDecimal(1.3) のように浮動小数点リテラルを使うと、すでに 2 進数表現による誤差を内部に含んだ値が作られてしまうためです。実務では、入力が文字列・ユーザー入力・CSV等から来る場合が多く、こうした文字列からの生成の方が安全です。

  2. スケールと丸めモードの明示
    除算(divide())で小数部の桁数・丸めモードを指定しないと、ArithmeticException がスローされる可能性があります。特に金額計算・単価計算など「必ず何桁以下で計算結果を示す」必要がある処理では、スケールと RoundingMode を明確に記述しましょう。

  3. パフォーマンスへの配慮
    BigDecimal は内部で任意精度の整数演算を行うため、四則演算や除算のたびにオブジェクト生成・メモリ操作が発生します。大量データや高頻度ループ処理、リアルタイム系の演算では doublelong といったプリミティブ型+補正処理(例えば「金額×100→long にして整数演算」)を併用検討することも現実的です。

  4. 比較処理の注意
    BigDecimal の比較には equals() ではなく compareTo() を使うのが一般的です。例えば new BigDecimal("1.0").equals(new BigDecimal("1.00")) は false ですが、compareTo() では 0(等価)を返します。使用目的に応じて適切な比較メソッドを選びましょう。

  5. コンテキストに応じたツール選択
    金額、為替、統計、計測値など「小数・精度が重要な値」の演算には BigDecimal が強力ですが、すべてに適用すべきというわけではありません。例えば「科学技術計算」「グラフィック演算」「高速な近似演算」などでは浮動小数点で十分だったり、むしろ高速化のためにそちらが適切だったりします。目的と制約(精度、性能、可読性、メモリ)を整理した上で、適切な型を選定してください。

Ads by Google

0 0
Article Rating
申し込む
注目する
guest
0 コメント一覧
最も古い
最新 高評価
インラインフィードバック
すべてのコメントを見る
0
あなたの考えが大好きです、コメントしてください。x