Rainbow Engine

IT技術を分かりやすく簡潔にまとめることによる学習の効率化、また日常の気付きを記録に残すことを目指します。

Java

Javaでdouble型での誤差を対処する方法について+サンプルプログラムも紹介

投稿日:2020年9月18日 更新日:

(1) Javaでの誤差の対処法
 (1-1) 対処が必要なケース
 (1-2) 対処の方法
  (1-2-1) BigDecimalクラスでの対処
  (1-2-2) int型を優先的に使い対処
  (1-2-3) double型の使い方を工夫して対処

(1) Javaでの誤差の対処法

誤差は小さいものの、累積していくと非常に大きな差分になる上に、if文等の比較では一致しなくなるため、問題となります。

(1-1) 対処が必要なケース

しかし、対処が必ずしも必要という訳ではなく、当然ながら対処した分は性能が落ちるため、システムの目的に応じて処置の有無も変わってきます。例えば、銀行のシステムなど誤差の許されない業務においては厳格な対処が必要となりますが、一方で科学分野などでは有効数字の概念など、そもそも非常に小さな値などは考慮しない考え方があるため、double型の誤差のオーダーでは処置不要と考えられます。

(表)

優先項目 対処方法 該当分野(例)
計算速度を優先
(対処不要)
・科学分野
・技術分野
(※有効数字など極小値は無視できるケースなどがある)
計算精度を優先 ①BigDecimalクラスを使う
②極力int型で計算を行う
③工夫してdouble型を使う

・金融系システム
(※お金の計算を伴うもの)

目次にもどる

(1-2) 対処の方法

上記で記載した①~③の対処方法について記述します。

(1-2-1) BigDecimalクラスでの対処

別記事にて詳細に記述(⇒★2020年9月中作成予定)

(1-2-2) int型を優先的に使い対処

もし計算プロセスの中で途中まででもintで進められるのであれば、intを使うようにします。もし除算など最後にdouble型が必要となる場面でのみdoubleを使う事で誤差を最小限に留める事ができます。

(サンプルPG)

public class IT0126_Double_Error {
        public static void main (String args[]) {
                d_err_sol1_p2(6.29,2.48,1.23);
        }

        public static void d_err_sol1_p2(double price1, double price2, double price3) {
                
                //引数(ドル)に100を掛けてセントに換算
                //その際にint型にキャストして、最後の除算まではint型で計算を進める
                int pc1 = (int)(price1*100);
                int pc2 = (int)(price2*100);
                int pc3 = (int)(price3*100);
                System.out.println("pc1= "+pc1+", pc2= "+pc2+", pc3= "+pc3);
                
                //極力int型で計算を進める
                int sum = pc1+pc2+pc3;
                
                //最後に割合を算出する時だけdouble型にキャストする
                //→除算前にキャストしないと、分母分子ともに小数点以下が切り捨てされてしまうため
                //→分子がdouble型にキャストされれば、分母は暗黙的にdouble型にキャストされる
                double rate1 = (double)pc1/sum;
                double rate2 = (double)pc2/sum;
                double rate3 = (double)pc3/sum;
                System.out.println("rate1= "+rate1+", rate2= "+rate2+", rate3= "+rate3);
        }

}

(図222)

(1-2-3) double型の使い方を工夫して対処

double型には誤差がある前提で、比較のロジックなどは通常は完全一致とする所を、誤差の分だけ「範囲」を持たせて比較するように変更します。

(サンプルPG)

public class IT0126_Double_Error2 {
        public static void main (String args[]) {

                //↓結果は10.0には戻らず、9.999999999999998になってしまう計算
                //そのため、10.0との誤差は(2E-15)となり次のif分岐で②の条件に合致する想定
                double db1 = 10.0 / 154.0 * 154.0;
				
                //①10.0と比較しても一致しない
                if(db1==10.0) {
                        System.out.println("完全一致で同じ値です");
                //②10.0±(10E-10)の範囲と一致するか?を確認
                }else if(doubleCheck(10.0,db1)) {
                        System.out.println("誤差±10E-10の範囲では一致します");
                //③それ以外のパターン(誤差が10E-10以上)
                }else {
                        System.out.println("誤差が±10E-10以上あります");
                }
        }
        //doubleCheck()メソッド
        //<処理概要>
        //引数に与えた2つのdouble型の変数の差の絶対値(abs)が10E-10の範囲内に収まっているか?の確認
        public static boolean doubleCheck(double d1, double d2) {
                System.out.println("d1= "+d1);
                System.out.println("d2= "+d2);
                return Math.abs(d1-d2) < 0.0000000001;
        }
}

(図223)

目次にもどる

Adsense審査用広告コード


Adsense審査用広告コード


-Java

執筆者:


comment

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

関連記事

Servlet(サーブレット)におけるフォワード(forward)とリダイレクト(redirect)の違い

<目次> (1) Servlet(サーブレット)におけるフォワード(forward)とリダイレクト(redirect)の違い  (1-1) フォワード(forward)とは?  (1-2) リダイレク …

Javaでcsvファイルに書き込みを行う方法(サンプルプログラム付き)

<目次> (1) Javaでcsvファイルに書き込みを行う方法  (1-1) 構文  (1-2) サンプルプログラム (1) Javaでcsvファイルに書き込みを行う方法 Javaでcsvファイルを生 …

サーブレットとは?その役割やHelloWorldサンプルコードのご紹介

(0)目次&概説 (1) サーブレットの基本  (1-1) サーブレットとは?  (1-2) サーブレットの前身技術との比較  (1-3) サーブレットとJSPの違い  (1-4) サーブレットのHe …

JavaのServletでフォーム認証(Form認証)をカスタム実装する方法

<目次> (1) JavaのServletでフォーム認証(Form認証)をカスタム実装する方法  (1-1) フォーム認証の概要  (1-2) フォーム認証をカスタムする際のポイント  (1-3) 構 …

Javaのstatic変数とは?その特徴及び付けた場合と付けない場合の違いを解説

(0)目次&概説 (1) static修飾子  (1-1) staticメンバとは?  (1-2) static変数   (1-2-1) static変数の説明と特徴   (1-2-2) static …

  • English (United States)
  • 日本語
Top