プロが教えるわが家の防犯対策術!

小数点以下の第50位を計算結果として表示させたいのですが、うまくいきません。

今は
BigDecimal BD = new BigDecimal("0.000・・・・");
double d;
----計算----
BD = new BigDecimal(d);
----表示----
として、表示させているのですが47桁くらいで終わってしまいます。
どうしたらいいのでしょうか。

情報が曖昧すぎますが、わかる方教えてください。

A 回答 (11件中1~10件)

#8>RoundingModeでエラーが出てしまいます。


#10の方がおっしゃる通りなので、
RoundingMode.HALF_EVEN
の部分は、
BigDecimal.ROUND_HALF_EVEN
で置き換えてみて下さい。(importもいらない)
>divide(BigDecimal val, int scale, int roundingMode)
でいう
「int roundingMode」は、数値の丸め方をintで指定したモノで処理するということです。
ここで指定できるintは、BigDecimalのpublic static final intとして定義されていますので、BigDecimal.ROUND_XXXXXXで使うことができます。
    • good
    • 1
この回答へのお礼

回答ありがとうございます。

書き方を変えたらエラーが全て消えました。
BigDecimal.ROUND_~は四捨五入や切り上げなどを行うようなものみたいですね。
全くわかりませんでした。

今は、Math.PIなどを使わずにBigDecimalのみでやっています。

円周率を出すにもイロイロな方法があるので驚きました。
今は記述するのに楽そうなものを使っていますが、なぜか3.30...とか出てしまいます。

お礼日時:2005/07/09 23:44

 こんばんは。


 #5です。

>RoundingModeがイマイチよく理解できません。

 RoundingModeクラスはJDK1.5から追加されたもので、列挙型として使用されます。
 ですので、1.4以前では、普通の整数型の定数を使います。

 たとえば、#5で書いた

>BigDecimal answer = x.divide(y, 50, RoundingMode.HALF_UP);

 は、1.4以前では使えません。
 1.4対応では、

BigDecimal answer = x.divide(y, 50, BigDecimal.ROUND_HALF_UP);

 こう書きます。
 似ていますが、二つは同じ機能の違うメソッドです。

 RoundingMode.HALF_UPは、RoundingModeクラスのインスタンス。
 BigDecimal.ROUND_HALF_UPは、整数型の定数という違いがあります。

 JDK1.4で勉強されているのなら、RoundingModeクラスのことは、まだ、考えなくていいと思います。
    • good
    • 0
この回答へのお礼

回答ありがとうございます。

>BigDecimal answer = x.divide(y, 50, BigDecimal.ROUND_HALF_UP);
このように書いたらエラーが消えました。

今は、Math.PTやMath.sinなどを使わずにやってみています。

お礼日時:2005/07/09 23:40

 #5です。



>>BigDecimal answer = x.divide(y, 50, RoundingMode.HALF_UP);
>この方法でやってみたのですが、RoundingMode.HALF_UPは解決できません。
>と出てしまいます。

 ごめんなさい。
 そのメソッドはJDK1.5からでした。

 1.4以前なら、

BigDecimal divide(BigDecimal val, int scale, int roundingMode)

http://java.sun.com/j2se/1.4/ja/docs/ja/api/java …

 を使ってください。

参考URL:http://java.sun.com/j2se/1.4/ja/docs/ja/api/java …
    • good
    • 0
この回答へのお礼

回答ありがとうございます。

divideでやってみたのですが、エラーが消えませんでした。
divide(BigDecimal val, int scale, int roundingMode)
val:BigDecimalの変数名
scale:桁数
だと思うのですが
roungindModeはこのまま入れればよろしいのでしょうか?
RoundingModeがイマイチよく理解できません。

お礼日時:2005/07/07 19:44

サンプルを作ってみました。


公式そのままなので、難しいところはないと思います。
(課題ということなので、丸写しするのではなくて、こんな感じでBigDecimalの計算をやるんだなぐらいに思って貰って、円周率を求める公式というのは、他にもいろいろあるので、そういうものやプログラムを検索して、自分でも作ってみてください。ていうか、多分削除されてしまうと思うしね。(削除されるにしても、何をどうしていいかわからん感じなので、書いてみました、このプログラムでは、収束ということを調べないで、これぐらいのループをすれば充分という感じでやってます。変更するなら、収束したかどうかでループを終了するようにしたらいいかと思います。その場合、無限ループに陥らないように、最初は、回数で制限を付けた方がいいかと思います。))
--------------------------------------------------------------------
import java.math.BigDecimal;
import java.math.RoundingMode;

//π/4=tan-1(1)=1-1/3+1/5-1/7+…は、収束が遅すぎる
/* ガウス・ルジャンドルの公式
1.初期値
a = 1
b = 1 / sqrt( 2 )
t = 1 / 4
x = 1
2.a と b が求めようとする精度以上に十分等しくなるまで下の式を反復
y = a
a = ( a + b ) / 2
b = sqrt( b ・ y )
t = t - x ・ ( y - a )^2
x = 2 ・ x
3.収束した a , b および t の値を用いて、πの値は、
π = ( a + b )^2 / ( 4 ・ t )
*/

public final class Pai {
static BigDecimal pai;
static int scale;
static {
Pai.pai = Pai.pai(100);//最初に100桁分求める
}
private Pai(){};
static public BigDecimal sqrt(BigDecimal a, int scale){
/* sqrt(a)=x=(x^2+a)/2x */
scale*=2;//2倍精度
a=a.setScale(scale, RoundingMode.HALF_EVEN);
BigDecimal x = a.divide(new BigDecimal(2), RoundingMode.HALF_EVEN);
int c=(int)Math.round(Math.log(scale)/Math.log(2));
for(int i=0;i<c;i++)
x=x.pow(2).add(a).divide(x.add(x),scale,RoundingMode.HALF_EVEN);
return x.setScale(scale/2, RoundingMode.HALF_EVEN);//精度を戻す
}
static public BigDecimal pai(int scale){
if(Pai.scale==scale){
return Pai.pai;
}
if(Pai.scale > scale){
//要求桁数が保持してる桁数より小さい時は、単に桁数を変換して返す
return pai.setScale(scale, RoundingMode.HALF_EVEN);
}
//要求される桁数が保持している桁数より大きいので、更新する
Pai.scale=scale;
scale*=2;//内部的に2倍の精度で計算する
BigDecimal one = BigDecimal.ONE;
BigDecimal two = new BigDecimal(2);
one=one.setScale(scale);
two=two.setScale(scale);
BigDecimal a = one;
BigDecimal b = one.divide(Pai.sqrt(two, scale), RoundingMode.HALF_EVEN);
BigDecimal t = one.divide(new BigDecimal(4), RoundingMode.HALF_EVEN);
BigDecimal x = one;
BigDecimal y;
int c=(int)Math.round(Math.log(scale)/Math.log(2));
for(int i=0;i<=c;i++){
y = a;
a = a.add(b).divide(two, RoundingMode.HALF_EVEN);
b = Pai.sqrt(b.multiply(y), scale);
t = t.subtract(x.multiply(y.subtract(a).pow(2)));
x = x.add(x);
}
Pai.pai=a.add(b).pow(2).divide(t.multiply(new BigDecimal(4)),scale,RoundingMode.HALF_EVEN);
Pai.pai=pai.setScale(Pai.scale, RoundingMode.HALF_EVEN);
return Pai.pai;
}

public static void main(String ar[]){
BigDecimal sqrt5 = Pai.sqrt(new BigDecimal(5),50);
System.out.println(sqrt5);
System.out.println(sqrt5.multiply(sqrt5));
System.out.println(Pai.pai(100));
System.out.println(Pai.pai(50));
}
}
    • good
    • 0
この回答へのお礼

回答ありがとうございます。

サンプルのほうですが、コピペで試させていただきましたがRoundingModeでエラーが出てしまいます。
setScaleではなく、divideで行ってみたのですが結果は同じでした。。。

お礼日時:2005/07/07 19:41

こんにちは、ソースを拝見しましたが


あまり自分の言ったことが伝わっていなかったようですね^^;

-------------足し算サンプルコード------------------
/* 全ての変数をBigDecimalに変換(有効桁数が50桁のデータで) */
BigDecimal bd = new BigDecimal("0.00000・・・");
BigDecimal bd2 = new BigDecimal("0.00000・・・");
/* 変換後のBigDecimalどうしで演算 */
bd = bd.add(bd2);
/* 表示 */
System.out.println(bd);
---------------------------------------------------

という意味だったのですが・・・

しかし、この場合すこし難しい気がします。
なぜかというと、

・問題1 精度
この中で使っている「Math.pi」自体がDouble精度のため
14~5桁の精度しか持たないのです。
そのため、この数値を用いて計算しても
50桁の精度の結果を得ることはできません。

・問題2 演算関数
計算に「Math.sin」を使っていますが、
この計算自体double型しか返せません。
また、BigDecimalにこれに相当する演算方法はありません。

有効桁数50桁で表示する際に用いる方法はBigDecimalしか
思いつきませんが、
この場合BigDecimalでも用件を満たすことができそうにありません。

課題であるならば、前提条件と満たすべき課題を
明確に教えていただけますか?
#どこかで認識違いがあるかも??
    • good
    • 0
この回答へのお礼

回答ありがとうございます。
返答が遅れて申し訳ありません。

BigDecimal同士ですと、50桁の計算も行えるようですが。
Math.PTを使うため、どうしてもdoubleが必要不可欠になってしまうみたいです。

課題内容ですが
「円周率πを50桁以上表示するプログラム作成」
です。

お礼日時:2005/07/06 23:55

#5補足>RoundingMode.HALF_UPは解決できません


import java.math.RoundingMode;
しないとRoundingModeの定数は使えませんです。

#5のリンク先見せて貰いましたけど、
単に、doubleの値をBigDecimalにしているだけなので、
#4>無限まで続いている数値になります
と言われているようなことはありません。
>d = Math.PI;

>pi = n * Math.sin(Math.PI / n);

単にdoubleの範囲で計算されていて、
その後
bd2 = new BigDecimal(pi);
bd2 = bd2.setScale(60);
としたとしても、有効桁は、setScaleで変更できますけども、
doubleの精度しかありません。
(多くの桁を表示させたとしても、単に表現誤差を表示しているに過ぎません)
もし、計算の目的が円周率を50桁求めることだとしたら、
doubleで計算してBigDecimalにするのではなくて、
初めから、BigDecimalで級数などによって計算しなければいけません。
    • good
    • 0
この回答へのお礼

回答ありがとうございます。

返答が遅くなり申し訳ありません。

>import java.math.RoundingMode;
これも足しましたが、解決できませんと出てしまったのです。

>doubleの精度しかありません。
確かに、d = Math.PI;もpi = n * Math.sin(Math.PI / n);も17,18桁以降は数値が違ってきていました。

>初めから、BigDecimalで級数などによって計算しなければいけません。
これをしたかったのですが、やり方がわからずにできませんでした。
Math.PTを使う時点でdoubleじゃなければダメみたいで。。

お礼日時:2005/07/06 23:43

 こんばんは。


 簡単な計算ですけど、これなら、ちゃんと50桁表示されました。

BigDecimal x = new BigDecimal("10");
BigDecimal y = new BigDecimal("3");
BigDecimal answer = x.divide(y, 50, RoundingMode.HALF_UP);
System.out.println(answer);

 実際どんなコードを書きましたか?
 そのまま載せると企業秘密に触れるとか、何かまずい事がある場合は、再現可能なサンプルでいいので、載せられませんか?
    • good
    • 0
この回答へのお礼

>BigDecimal answer = x.divide(y, 50, RoundingMode.HALF_UP);
この方法でやってみたのですが、RoundingMode.HALF_UPは解決できません。と出てしまいます。

ソースコードのほうです。
http://www.hayasoft.com/peach-heaven/Test.java
学校の課題でやっているものですので、秘密などは無いのです。

お礼日時:2005/07/04 22:37

質問の意図があまりよくつかめていなかったようです。


申し訳ありません。

つまり、double型で計算した結果を無理やり50桁目まで0埋めしたいということですか?
それならば、無理やりフォーマットしても誤差が見えてしまうだけになりますし、ロジックを組んで無理やり0埋めすべきだとおもいます。

もしそうでなく、最大で50桁までいく可能性があるから、ということならば
計算をdouble等を使って行わずに、全てBigDecimalの関数を使った計算をするべきだと言いたかったのですが・・・
(例に挙げたのは加算だけですが、四則演算全て用意されています。)

計算ロジックの記述は面倒になりますが、
正確な値がほしい場合は、
全ての計算に使う数字をBigDecimalの形にして、BigDecimalの演算メソッドを使って計算を行うべきですね。
    • good
    • 0
この回答へのお礼

0埋めという結果にはならない計算です。
計算結果は0.3333・・・のように無限まで続いている数値になりますので。

>全ての計算に使う数字をBigDecimalの形にして
これも実際行ってみたのですが、やり方が悪いのか"doubleからBigDecimalへのキャストはできません"とエラーが出てしまいます。

お礼日時:2005/07/04 18:42

これで今47桁まで出ているのですか。

。。

まず、現在の構成について
>BigDecimal BD = new BigDecimal("0.000・・・・");
この部分で小数点第50位まであるBigDecimalのインスタンスを作成していますが
>BD = new BigDecimal(d);
でdouble型のdをBigDecimal型にしたもので上書きしてますね。
なので、当然double型での計算時に47桁までしかなければ、そこまでしか表示されません。

対策ですが、
BigDecimalを使うならば計算もBigDecimalでやるべきです。
たとえば以下のようにすれば問題ないはずです。

-------------足し算サンプルコード------------------
BigDecimal bd = new BigDecimal("0.00000・・・");
BigDecimal bd2 = new BigDecimal("0.00000・・・");
bd = bd.add(bd2);
System.out.println(bd);
---------------------------------------------------
    • good
    • 0
この回答へのお礼

回答ありがとうございます。

計算結果として受け取れるのがdoulbeだけで、そのまま表示したら17,18桁くらいでした。
ですが、要求されているのが50桁以上を表示というものですのでBigDecimalを使っています。

お礼日時:2005/07/04 12:24

プログラミング言語でのこの手の問題は



数学演算用ライブラリーを利用する。とか
自分で50桁以上対応の演算ライブラリを作成する。とか
そういった回答が昔からありますね。

今もそうするしかないのかどうかは知りません。
    • good
    • 0
この回答へのお礼

回答ありがとうございます。

>数学演算用ライブラリーを利用する。とか
>自分で50桁以上対応の演算ライブラリを作成する。とか

そうなのですか。。。
できそうに無いです・・・。

お礼日時:2005/07/04 12:09

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!