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

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

関連記事

JVMの基本アーキテクチャと各サブシステム等の概要説明について

(0)目次&概説 (1) 記事の目的 (2) Javaのアーキテクチャ概要・概観 (3) JVMのアーキテクチャ概要  (3-1) JVMの概観  (3-2) JVMの主要サブシステム1:Class …

TwitterのAPIでハッシュタグからツイートを探すJavaプログラムのご紹介

<目次> (1) TwitterのAPIでハッシュタグからツイートを探すJavaプログラムのご紹介  (1-1) プログラムの概要  (1-2) サンプルプログラム  (1-3) 操作イメージ (1) …

JavaScriptのMapとは?基本的な使い方やサンプルプログラムをご紹介

<目次> (1) JavaScriptのMapとは?基本的な使い方やサンプルプログラムをご紹介  (1-1) 概要・構文  (1-2) サンプルプログラム   ●JavaScriptのサンプル   ● …

Javaの型とは?ジェネリクスの基本や使い方をご紹介

<目次> (1) Javaの型とは?ジェネリクスの基本や使い方をご紹介  (1-1) <T>とは?ジェネリクスとは?  (1-2) ジェネリクスを使う利点  (1-3) ジェネリクスをクラ …

Javaのabstractとは?抽象クラスの概要やサンプルPGをご紹介

<目次> (1) Javaのabstractとは?抽象クラスの概要やサンプルPGをご紹介  (1-1) 抽象クラス(abstract)とは  (1-2) 抽象クラスの目的や用途  (1-3) 抽象クラ …

  • English (United States)
  • 日本語
Top