• ベストアンサー

計算する度にBigDecimalオブジェクト作成?

javaのDouble型の足し算をするには、BigDecimalを使わなければ 正確な数値が得られない、ということで使用したのですが、 毎回、小数点の足し算をする度に、 負荷のかかるnew宣言でBigDecimalのインスタンスを作りaddメソッドで計算するというはどうも非効率に思ってしまうのです、、; javaでの小数点の足し算は皆さん通常どうやっているのでしょうか?

質問者が選んだベストアンサー

  • ベストアンサー
  • salsberry
  • ベストアンサー率69% (495/711)
回答No.1

大概の演算はdouble型の演算精度で足りますし、演算誤差を減らすような演算方法も色々知られています。 double型では有効桁数がどうやっても足りないとか、10進←→2進の変換に伴う誤差を嫌う場合にはBigDecimalを使うしかないかもしれません。

bajiriko
質問者

お礼

ありがとうございました。

bajiriko
質問者

補足

「誤差を減らすような演算方法」の具体例などがあれば教えて頂ければありがたいです。 二進数double型の計算結果をどの様な基準で丸めればよいか?に悩んでいたので、 それならば、とString→BigDecimal→Stringで扱おうと思ったしだいです。

全文を見る
すると、全ての回答が全文表示されます。

その他の回答 (5)

回答No.6

> クライアントがもたらすランダムな引数を四則計算する場合は、 > 四則別にそれぞれ誤差を出さない計算方法のセオリーなどがあるのでしょうか? 例えば 1.0 / 3.0 を誤差なしで保持する数値型は Java に用意されていません。 結局誤差を制御するには誤差を見積もって計算に必要な精度を見積もるしかなく 簡単なルールといったものはありません。

bajiriko
質問者

お礼

BigDecimalでも、1.0/3.0は誤差が出るのですね? 知らなかったです。 やはり、自分で結果を制御する式を作るしかないのですね。。 ありがとうございました。

全文を見る
すると、全ての回答が全文表示されます。
  • salsberry
  • ベストアンサー率69% (495/711)
回答No.5

> クライアントがもたらすランダムな引数を四則計算する場合は、 > 四則別にそれぞれ誤差を出さない計算方法のセオリーなどがあるのでしょうか? 「○○方程式を××法を使って解く場合に、計算方法や手順をこうすれば誤差を減らせる」のように特定の問題領域についてのノウハウは様々ありますが、完全に任意の値、任意の演算だと無理でしょうね。

bajiriko
質問者

お礼

ランダムな引数な場合、 望んだ結果を出すように自分で導くしかないんですね。 誤差が出ないような式を造り、どのタイミングで使うか、検討してみます。 ありがとうございました。

全文を見る
すると、全ての回答が全文表示されます。
  • salsberry
  • ベストアンサー率69% (495/711)
回答No.4

> 「誤差を減らすような演算方法」の具体例などがあれば教えて頂ければありがたいです。 ごくごく単純な例を挙げます。3.1から4.0まで0.1刻みの値を得ようとするものですが、3.3のところからxとyで差が出ていることが分かりますよね。 double x=3.0; double y0=3.0, y; for (int i=1; i<=10; i++) { x += 0.1; y = y0+0.1*i; System.out.println("x="+x+", y="+y); } x=3.1, y=3.1 x=3.2, y=3.2 x=3.3000000000000003, y=3.3 x=3.4000000000000004, y=3.4 x=3.5000000000000004, y=3.5 x=3.6000000000000005, y=3.6 x=3.7000000000000006, y=3.7 x=3.8000000000000007, y=3.8 x=3.900000000000001, y=3.9 x=4.000000000000001, y=4.0

bajiriko
質問者

お礼

ありがとうございました。

bajiriko
質問者

補足

なるほど!xが三回目から累積誤差を出しているのを見て、 yは毎回新しい値で累積させないようにしているのですね。 今回は、計算する値、計算方法、回数、結果、が定まっていたケースですが、 たとえば、クライアントがもたらすランダムな引数を四則計算する場合は、 四則別にそれぞれ誤差を出さない計算方法のセオリーなどがあるのでしょうか? その公式の様な物が紹介されているサイトがあれば良いのですが、、。

全文を見る
すると、全ての回答が全文表示されます。
回答No.3

>javaのDouble型の足し算をするには、BigDecimalを使わなければ >正確な数値が得られない これはどこの情報なんでしょうか? BigDecimalは強力ですけど、「必要な精度」が double で十分ならば、 doubleで処理した方がはるかに効率的です。 doubleの精度は 10進だと 16桁強です。

bajiriko
質問者

お礼

ありがとうございました。

bajiriko
質問者

補足

小数点の計算をして下記と同じ様な症状が出たのでBigDecimalを使いました。 http://javafaq.jp/S029.html このサイトの [S029-Q01] です。

全文を見る
すると、全ての回答が全文表示されます。
  • Gotthold
  • ベストアンサー率47% (396/832)
回答No.2

科学技術系の計算なら大抵はdouble型の精度で十分です。 (それに10進数については丸め誤差がでないと言うことにさほど意味がない。) (お金の事務計算などで)2進-10進の変換での誤差を気にするなら 最初から最後までBigDecimalを使うべきで double型を経由するべきではないと思います。

bajiriko
質問者

お礼

ありがとうございました。

bajiriko
質問者

補足

そうですね。誤差は気になります。 ただ、自分で丸めるのも、 BigDecimalで丸めるのも同じとなるとBigDecimalを使う意味がなくなりますが、、。

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • BigDecimal小数計算について

    プログラミングに関する知識が皆無の初心者です。 「はじめてのandroidアプリプログラミング」という本に従って電卓のアプリを作っているのですが、小数点を含む計算ができず、困っております。 演算記号前の数字が小数で、演算記号後の数字が整数であるならば 1.5*2=3 と正しく計算ができますが、 演算記号後が小数点を含む数だと、計算されず演算記号後に入力した数字が 2*1.5=1.5 と、そのまま表示されてしまいます。 小数の表示は if (mOp == R.id.button_decimal || mCalcValue.scale() != 0) {  // 小数点を含む場合  BigDecimal bd = new BigDecimal(BigInteger.valueOf(value),mCalcValue.scale() + 1);  mCalcValue = mCalcValue.add(bd); } else {  // それ以外の場合  // 10倍  mCalcValue = mCalcValue.multiply(BigDecimal.TEN);  // 足す  mCalcValue = mCalcValue.add(new BigDecimal(value)); } で、 イコールを押したときの動作は public void onEqualClick(View view) {  switch (mOp) {   case R.id.button_plus:   // 足し算   mCalcValue = mPreValue.add(mCalcValue);   break;   case R.id.button_subtract:   // 引き算   mCalcValue = mPreValue.subtract(mCalcValue);   break;   case R.id.button_multiply:   // かけ算   mCalcValue = mPreValue.multiply(mCalcValue);   break;   case R.id.button_divide:   // 現在の値が0ではないかチェック   if (!BigDecimal.ZERO.equals(mCalcValue)) {    // 割り算    mCalcValue = mPreValue.divide(mCalcValue, 11,    BigDecimal.ROUND_HALF_UP);   }  break; } です。 どこのコードが原因かもわからず、どこを質問文に掲示すればアドバイスいただきやすいかもわからなかったため、質問文に不足あるかもしれません。 すみませんがよろしくお願いします。

    • ベストアンサー
    • Java
  •  Javaでのある数の小数点乗について

     Javaでのある数の小数点乗について  数学での計算をJavaを使って計算している所です。Javaの中でもDoubleを使うのではなく、BIgDecimalクラスを使って計算をしています。しかし、BigDecimalの値をBigDecimal乗するという事は出来ないですよね? Math.powを使えばDouble型のDouble乗は出来ますが…  そこで、任意の精度で小数点の小数点乗を求める方法は無いでしょうか? 必要ないかもしれませんが参考までに 言語:Java OS:MacOS 10.5

    • ベストアンサー
    • Java
  • DoubleからBigDecimalへの変更の仕方

    以下のソースをdouble使用箇所をBigDecimalに変更して行いたいのですが・・・ public String test( String str1, String str2){ // 計算方法: // str1 / str2 の小数点第3位切り上げ後に100掛け // 割り算を行う double d = Double.valueOf(str1).doubleValue()/Double.valueOf(str2).doubleValue(); // 掛け算を行う d = d*100; // 小数点第1位切り上げる if (d >= 10.88) { d = 11; } DecimalFormat ff = new DecimalFormat("#0.0"); return ff.format(d); }

    • ベストアンサー
    • Java
  • 電卓アプリで%キーの計算プログラムについて

    現在、Androidのアプリ作成の勉強に励んでいます。 まず、手始めに電卓アプリを作りながら学んでいますが、 電卓キーの「%キー」をClickした時の計算プログラムがどうしても考えつきません。 できれば、BigDecimalメソッドを使って「%キー」の計算をさせることができればと 思っています。 doCalcというメソッドを作ってその中に計算プログラムを書いていて doCalcメソッドの中身(足し算、引き算、乗算、除算についての計算プログラム)についての計算プログラム)は下記のとおりです。 是非、ご教授いただければ助かります。 またBigDecimalメソッドを使わず他のやりかたでも結構ですので、参考にご教授いただければ幸いです。 宜しくお願いいたします。 //strResult=入力中の数値 //strTemp=入力が完了した数値と計算結果で共有 private String doCalc() { BigDecimal bd1=new BigDecimal(strResult); BigDecimal bd2=new BigDecimal(strTemp); BigDecimal result=BigDecimal.ZERO; switch(operator) { case R.id.KeypadAdd: result=bd1.add(bd2); break; case R.id.KeypadSub: result=bd1.subtract(bd2); break; case R.id.KeypadMulti: result=bd1.multiply(bd2); break; case R.id.KeypadDiv: if(!bd2.equals(BigDecimal.ZERO)){ result=bd1.divide(bd2, 12, 3); }else{ Toast toast=Toast.makeText(this,R.string.toast_div_by_zero,1000); toast.show(); } break; } if(result.toString().indexOf(".")>=0){ return result.toString().replaceAll("\\.0+$|0+$",""); }else{ return result.toString(); } }

  • 少数50桁以上を表示するには

    小数点以下の第50位を計算結果として表示させたいのですが、うまくいきません。 今は BigDecimal BD = new BigDecimal("0.000・・・・"); double d; ----計算---- BD = new BigDecimal(d); ----表示---- として、表示させているのですが47桁くらいで終わってしまいます。 どうしたらいいのでしょうか。 情報が曖昧すぎますが、わかる方教えてください。

    • ベストアンサー
    • Java
  • 複数の数字を計算

    下記のプログラムだと、 1 tasu 1 tasu 1 tasu 1 tasu 1 をしても答えは2となります。 入力された数字を一気に計算できる方法を教えて下さい。 また、必ず5の値を入力しなくては、いけないのでは無くて、5つ以下ならOKにしたいです。 コマンドプロンプト上で自ら入力し動くプログラムを作成中です。 例: 1 tasu 1 tasu 1 tasu 1 tasu 1  答え5      1 tasu 1 tasu 1 答え3 /*演算子チェックと演算実行*/ if (args[1].equals("tasu")){ /*演算子チェック*/ ans1 = num1 + num2; }else if (args[1].equals("hiku")){ /*演算子チェック*/ ans1 = num1 - num2; /* hiku 演算実行*/ }else if (args[1].equals("kake")){ /*演算子チェック*/ ans1 = num1 * num2; /* kake 演算実行*/ }else if (args[1].equals("waru")){ /*演算子チェック*/ if(num2 == 0){ /*0算チェック*/ System.out.println("0で割ろうとしました"); }else{ BigDecimal bd1 = new BigDecimal(num1); /* waru 演算実行*/ BigDecimal bd2 = new BigDecimal(num2); BigDecimal bd3 = bd1.divide(bd2, 2, BigDecimal.ROUND_HALF_UP);/*小数点第3位四捨五入、小数点第2位まで表示の割り算*/ } }else{ System.out.println("演算子1: kake waru tasu hiku の中から入力して下さい"); } /*演算子チェックと演算実行*/ if (args[3].equals("tasu")){ /*演算子チェック*/ ans1 = num2 + num3; }else if (args[3].equals("hiku")){ /*演算子チェック*/ ans1 = num2 - num3; /* hiku 演算実行*/ }else if (args[3].equals("kake")){ /*演算子チェック*/ ans1 = num2 * num3; /* kake 演算実行*/ }else if (args[3].equals("waru")){ /*演算子チェック*/ if(num3 == 0){ /*0算チェック*/ System.out.println("0で割ろうとしました"); }else{ BigDecimal bd1 = new BigDecimal(num2); /* waru 演算実行*/ BigDecimal bd2 = new BigDecimal(num3); BigDecimal bd3 = bd1.divide(bd2, 2, BigDecimal.ROUND_HALF_UP);/*小数点第3位四捨五入、小数点第2位まで表示の割り算*/ } }else{ System.out.println("演算子2: kake waru tasu hiku の中から入力して下さい"); } /*演算子チェックと演算実行*/ if (args[5].equals("tasu")){ /*演算子チェック*/ ans1 = num3 + num4; }else if (args[5].equals("hiku")){ /*演算子チェック*/ ans1 = num3 - num4; /* hiku 演算実行*/ }else if (args[5].equals("kake")){ /*演算子チェック*/ ans1 = num3 * num4; /* kake 演算実行*/ }else if (args[5].equals("waru")){ /*演算子チェック*/ if(num4 == 0){ /*0算チェック*/ System.out.println("0で割ろうとしました"); }else{ BigDecimal bd1 = new BigDecimal(num3); /* waru 演算実行*/ BigDecimal bd2 = new BigDecimal(num4); BigDecimal bd3 = bd1.divide(bd2, 2, BigDecimal.ROUND_HALF_UP);/*小数点第3位四捨五入、小数点第2位まで表示の割り算*/ } }else{ System.out.println("演算子3: kake waru tasu hiku の中から入力して下さい"); } /*演算子チェックと演算実行*/ if (args[7].equals("tasu")){ /*演算子チェック*/ ans1 = num4 + num5; }else if (args[7].equals("hiku")){ /*演算子チェック*/ ans1 = num4 - num5; /* hiku 演算実行*/ }else if (args[7].equals("kake")){ /*演算子チェック*/ ans1 = num4 * num5; /* kake 演算実行*/ }else if (args[7].equals("waru")){ /*演算子チェック*/ if(num5 == 0){ /*0算チェック*/ System.out.println("0で割ろうとしました"); }else{ BigDecimal bd1 = new BigDecimal(num4); /* waru 演算実行*/ BigDecimal bd2 = new BigDecimal(num5); BigDecimal bd3 = bd1.divide(bd2, 2, BigDecimal.ROUND_HALF_UP);/*小数点第3位四捨五入、小数点第2位まで表示の割り算*/ } }else{ System.out.println("演算子4: kake waru tasu hiku の中から入力して下さい"); }

    • ベストアンサー
    • Java
  • double型の減算がうまくいかない

    Java初心者です。 今、Javaの勉強中で、double型の計算を行っています。 double型同士の減算を行った結果、思っていた結果と違う値が帰ってきたので、原因、もしくは解決方法をお教え頂ければと思います。 ソースは以下 public static void main(String[] args) { //値A double longitudeA = -73.98289; //値B double longitudeB = -73.98315; BigDecimal aDecimal = new BigDecimal(String.valueOf(longitudeA)); BigDecimal bDecimal = new BigDecimal(String.valueOf(longitudeB)); //減算 BigDecimal decimal = aDecimal.subtract(bDecimal); //小数点以下第5位で四捨五入し、出力 System.out.print(decimal.setScale(5, RoundingMode.HALF_UP).doubleValue()); } 出力される値として、 0.00026 を想定していたのですが、実際に出力されたのは 2.6E-4 でした。 BigDecimalのオブジェクトをそのまま出力すると想定通りの結果が出力されます。 一回Stringに型変換を行った後、Double#parseDoubleを行ったりしてみたのですが、 どうも思った通りの出力がされません。 解決策をお教え頂ければと思います。 よろしくお願いします。

  • 小数点以下切捨てした上での足し算

    書式設定で小数点以下の桁数0にし、整数での表示にさせています。 しかしそれらを足し算すると結局正確に小数点以下の数値まで 足されてしまいます。そうしないためには?

  • JAVAアプレット(簡易計算機)のプログラム

    足し算を行うだけのプログラムを組むことができたのですが、 四則演算を行いたいと考えています。 下記のようなプログラムでは、ボタンが=のボタンなのですが、 そのボタンを+,-,*,/の4つにおきかえて、各ボタンを押したときに 各ボタンの処理を行うのはどのようにすればいいのでしょうか? 分かる方、ご教授よろしくおねがいします。 import java.applet.Applet; import java.awt.*; // java.awtパッケージのインポート import java.awt.event.*; public class SampleD10L2 extends Applet { private Button btn_culc; // +ボタン private TextField txt_A, txt_B, txt_answer; // 数値入力用テキストボックス public void init() { // ボタンのインスタンスを作成 btn_culc = new Button("="); // ボタンのイベント処理を定義 btn_culc.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) { // txt_Aに入力された値 + txt_Bに入力された値を計算 int intAnswer = Integer.parseInt(txt_A.getText()) + Integer.parseInt(txt_B.getText()); // 答えをtxt_answerに表示 txt_answer.setText(Integer.toString(intAnswer)); } }); // コンポーネントの初期化 txt_A = new TextField("0", 3); txt_B = new TextField("0", 3); lbl_plus = new Label(" + "); txt_answer = new TextField("0", 5); // コンポーネントを追加 this.add(txt_A); // 自分自身のaddメソッドを呼び出す(this.は省略可能) this.add(lbl_plus); this.add(txt_B); this.add(btn_culc); this.add(txt_answer); } }

    • ベストアンサー
    • Java
  • 複素数の計算するクラスを足せる人がもしいたら

    このJavaプログラムはAdd(足し算)とSud(引き算)を計算するプログラムです。 import Java.io.*; class INT { public int Add(int x,int y){ return x+y; } public int Sub(int x,int y){ return x-y; } } class REAL extends INT { public double Add( double x,double y){ return x+y; } public double Sub( double x,double y){ return x-y; } } class CAL extends REAL { } … public class Cale { public static void main(String args[]) { CAL c = new CAL(); System.out.println( c.Add(1,2) ); System.out.println( c.Add(1.0,2.0)); System.out.println( c.Sub( 1,2)); System.out.println( c.Sub( 1.0,2.0)); } } このプログラムに「複素数の足し算と引き算をするクラス」をクラスの仕様も併せて 作成することが出来る人がもしいたら宜しくおねがいします☆