• ベストアンサー

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

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

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

  • ベストアンサー
  • BLUEPIXY
  • ベストアンサー率50% (3003/5914)
回答No.11

#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で使うことができます。

Shangrila
質問者

お礼

回答ありがとうございます。 書き方を変えたらエラーが全て消えました。 BigDecimal.ROUND_~は四捨五入や切り上げなどを行うようなものみたいですね。 全くわかりませんでした。 今は、Math.PIなどを使わずにBigDecimalのみでやっています。 円周率を出すにもイロイロな方法があるので驚きました。 今は記述するのに楽そうなものを使っていますが、なぜか3.30...とか出てしまいます。

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

その他の回答 (10)

  • PecoPlus
  • ベストアンサー率76% (144/188)
回答No.10

 こんばんは。  #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クラスのことは、まだ、考えなくていいと思います。

Shangrila
質問者

お礼

回答ありがとうございます。 >BigDecimal answer = x.divide(y, 50, BigDecimal.ROUND_HALF_UP); このように書いたらエラーが消えました。 今は、Math.PTやMath.sinなどを使わずにやってみています。

全文を見る
すると、全ての回答が全文表示されます。
  • PecoPlus
  • ベストアンサー率76% (144/188)
回答No.9

 #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/math/BigDecimal.html#divide(java.math.BigDecimal,%20int,%20int)  を使ってください。

参考URL:
http://java.sun.com/j2se/1.4/ja/docs/ja/api/java/math/BigDecimal.html#divide(java.math.BigDecimal,%20int,%20int)
Shangrila
質問者

お礼

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

全文を見る
すると、全ての回答が全文表示されます。
  • BLUEPIXY
  • ベストアンサー率50% (3003/5914)
回答No.8

サンプルを作ってみました。 公式そのままなので、難しいところはないと思います。 (課題ということなので、丸写しするのではなくて、こんな感じで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)); } }

Shangrila
質問者

お礼

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

全文を見る
すると、全ての回答が全文表示されます。
  • shin_5696
  • ベストアンサー率39% (21/53)
回答No.7

こんにちは、ソースを拝見しましたが あまり自分の言ったことが伝わっていなかったようですね^^; -------------足し算サンプルコード------------------ /* 全ての変数を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でも用件を満たすことができそうにありません。 課題であるならば、前提条件と満たすべき課題を 明確に教えていただけますか? #どこかで認識違いがあるかも??

Shangrila
質問者

お礼

回答ありがとうございます。 返答が遅れて申し訳ありません。 BigDecimal同士ですと、50桁の計算も行えるようですが。 Math.PTを使うため、どうしてもdoubleが必要不可欠になってしまうみたいです。 課題内容ですが 「円周率πを50桁以上表示するプログラム作成」 です。

全文を見る
すると、全ての回答が全文表示されます。
  • BLUEPIXY
  • ベストアンサー率50% (3003/5914)
回答No.6

#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で級数などによって計算しなければいけません。

Shangrila
質問者

お礼

回答ありがとうございます。 返答が遅くなり申し訳ありません。 >import java.math.RoundingMode; これも足しましたが、解決できませんと出てしまったのです。 >doubleの精度しかありません。 確かに、d = Math.PI;もpi = n * Math.sin(Math.PI / n);も17,18桁以降は数値が違ってきていました。 >初めから、BigDecimalで級数などによって計算しなければいけません。 これをしたかったのですが、やり方がわからずにできませんでした。 Math.PTを使う時点でdoubleじゃなければダメみたいで。。

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

 こんばんは。  簡単な計算ですけど、これなら、ちゃんと50桁表示されました。 BigDecimal x = new BigDecimal("10"); BigDecimal y = new BigDecimal("3"); BigDecimal answer = x.divide(y, 50, RoundingMode.HALF_UP); System.out.println(answer);  実際どんなコードを書きましたか?  そのまま載せると企業秘密に触れるとか、何かまずい事がある場合は、再現可能なサンプルでいいので、載せられませんか?

Shangrila
質問者

お礼

>BigDecimal answer = x.divide(y, 50, RoundingMode.HALF_UP); この方法でやってみたのですが、RoundingMode.HALF_UPは解決できません。と出てしまいます。 ソースコードのほうです。 http://www.hayasoft.com/peach-heaven/Test.java 学校の課題でやっているものですので、秘密などは無いのです。

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

質問の意図があまりよくつかめていなかったようです。 申し訳ありません。 つまり、double型で計算した結果を無理やり50桁目まで0埋めしたいということですか? それならば、無理やりフォーマットしても誤差が見えてしまうだけになりますし、ロジックを組んで無理やり0埋めすべきだとおもいます。 もしそうでなく、最大で50桁までいく可能性があるから、ということならば 計算をdouble等を使って行わずに、全てBigDecimalの関数を使った計算をするべきだと言いたかったのですが・・・ (例に挙げたのは加算だけですが、四則演算全て用意されています。) 計算ロジックの記述は面倒になりますが、 正確な値がほしい場合は、 全ての計算に使う数字をBigDecimalの形にして、BigDecimalの演算メソッドを使って計算を行うべきですね。

Shangrila
質問者

お礼

0埋めという結果にはならない計算です。 計算結果は0.3333・・・のように無限まで続いている数値になりますので。 >全ての計算に使う数字をBigDecimalの形にして これも実際行ってみたのですが、やり方が悪いのか"doubleからBigDecimalへのキャストはできません"とエラーが出てしまいます。

全文を見る
すると、全ての回答が全文表示されます。
  • shin_5696
  • ベストアンサー率39% (21/53)
回答No.3

これで今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); ---------------------------------------------------

Shangrila
質問者

お礼

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

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

プログラミング言語でのこの手の問題は 数学演算用ライブラリーを利用する。とか 自分で50桁以上対応の演算ライブラリを作成する。とか そういった回答が昔からありますね。 今もそうするしかないのかどうかは知りません。

Shangrila
質問者

お礼

回答ありがとうございます。 >数学演算用ライブラリーを利用する。とか >自分で50桁以上対応の演算ライブラリを作成する。とか そうなのですか。。。 できそうに無いです・・・。

全文を見る
すると、全ての回答が全文表示されます。
  • BLUEPIXY
  • ベストアンサー率50% (3003/5914)
回答No.1

BD=BD.setScale(50); とかして有効桁を設定して、 あと、計算するときに Scaleを減らさないようなメソッドを使って計算していますか

Shangrila
質問者

お礼

回答ありがとうございます。 有効桁数を設定しましたが、Scaleを減らさないようにする方法がわかりません。

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

関連するQ&A

  • エクセルで小数点以下3桁を四捨五入して、小数点以下1桁を表示する方法

    エクセル2003を使用しています。 計算式から出た結果に対して、小数点以下3桁を四捨五入して、小数点以下2桁ではなく、1桁を表示したいです。 例えば、計算式の結果、 1.145 の場合、普通に四捨五入すると 小数点以下1桁なら、1.1 小数点以下2桁なら、1.15 となってしまいます。 これを小数点以下3桁を四捨五入して、小数点以下1桁表示の1.2と表示させたいのですが、可能でしょうか?

  • 少数点以下2桁以上の入力でエラーメッセージを表示するには

    データの入力規則で、少数点以下2桁以上の数値が入力されたらエラーメッセージが表示されるようにできないでしょうか? (小数点以下1桁[3.2→OK]  小数点以下2桁[3.26→エラーメッセージ]) または、条件付き書式で上記条件でセルの色を変えることはできますか? よろしくお願いします。

  • エクセルで整数表示と少数表示を混在させたい

    お世話になります。 集計用のファイルを作っています。 整数と、小数点以下1桁、2桁の数値が出てきます。 書式設定で小数点以下2桁まで表示するようにしたら、整数や小数点以下1桁の数値まで120.00とか25.50と表示されてしまい、見にくくなってしまいました。 小数点以下に0がつく場合は無視して、それぞれ120、25.5、3.25のように必要な桁数だけ表示させたいのですが、どうしたらよいでしょうか。

  • 電卓の表示(いつもは0桁、割り切れないとき2桁)

    キャノンのHS-1220TUGという電卓使ってます。 計算後の答えなんですが、割り切れないときだけ小数点2桁表示(3桁目を四捨五入)で、それ以外は0桁に表示するやり方ありませんか? いつもはFで四捨五入してるんですが、これだといつも小数点2桁まで表示されちゃうから見づらいんです。

  • 18桁の割り算をしたい

    それほど多くはないですが、今の仕事で分母が18桁、分子が16桁の分数を小数に計算をしなくてはならなくなりました。(小数点以下5桁ほど) 手持ちの計算機ではできず困っています。 何か、計算できるソフトのようなものがあれば教えて下さい。

  • 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
  • 1セルに6桁以上入力できない。小数点以下の表示が00になってしまう。

    エクセルの1つのセルに1,000,000と入力するも1,000となってしまいます。 数式と値をクリアにしても、表示形式を標準や数値や文字列に設定しても下3桁が入りません。 それと小数点第2位まで計算したいのに、小数点第2位は.00なってしまいます。 それと小数点以下を切り捨てで表示させたいのに、四捨五入になってしまいます。

  • Accessの桁区切りについて教えてください。

    アクセスのレポートの金額に、桁区切りのカンマを付けたいと思っています。 プロパティの書式を通貨にすると¥マークがついてしまいます。 合計は付いてもいいのですが、内訳には¥マークを付かないように桁区切りだけにしたいのです。 そのため、書式に『###,##0』としました。 できましたが、小数点以下が表示されません。 小数点を表示したいので『###,##0.###』としたら、『59,180.000』となってしまいます。 小数点の指定を自動から3桁表示に変えましたが、うまくいきません。 教えていただきたい内容としては、 ・金額の表示に桁区切りのカンマを付けたい。 ・でも¥マークは付けたくない。 ・小数点以下該当があるもののみ3桁まで表示させたいが(5,500.365)、  小数点以下がないものは小数点以下は表示させたくない(5,400)。 ぜひともアクセスを使いこなしている方、お教えください。

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

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

    • ベストアンサー
    • Java
  • テキストボックスの少数点以下表示について

    お願いします。 アクセス2002を使っています。 フォームのテキストボックスの数値表示についてお尋ねします。 たとえば「1.75」という小数点以下2桁まで表示させたいのですが、コントロールで書式を「標準」に、小数点以下表示桁数を「2」と指定しても結果は「2.00」と表示されます。 入力した1.75をそのまま1.75で表示させるにはどうすればいいのでしょうか。 宜しくお願いします。