- ベストアンサー
円周率を求めるプログラム
428224593349304/136308121570117を解いて小数点以下30桁まで求めたいのですが、こういう場合どのようにしてやればいいんですか? 友達は、428224593349304を1桁ずつ配列に入れて手計算でやるようにすればできると言っていたのですが、考え方がさっぱりわかりません。 もし配列を使って求めるとしたらどのような計算をさせたらいいのかもう少し具体的に教えてください。
- みんなの回答 (6)
- 専門家の回答
質問者が選んだベストアンサー
例えば、掛け算と引き算は、 const int N = 2; void multiply( int a[], int b, int c[] ) { int x = 0; for ( int i=N; i>=1; i-- ) { x += a[i] * b; if ( x < 10 ) { c[i] = x; x = 0; } else { c[i] = x % 10; x /= 10; } } c[0] = x; } void substraction( int a[], int b[], int c[] ) { for ( int i=N; i>=1; i-- ) { c[i] = a[i] - b[i]; if ( c[i] < 0 ) { c[i] += 10; a[i-1] -= 1; } } c[0] = a[0] - b[0] } int A[N+1] = { 0, 4, 2 }; int B[N+1] = { 0, 1, 9 }; int C[N+1] = { 0, 0, 0 }; int D[N+1] = { 0, 0, 0 }; multiply( B, 2, C ); substraction( A, C, D ); のような関数だと思います。ただ、これはあくまで考え方であって、実際にはNo.4の方が書かれているような問題を解決しなくてはならないと思います。
その他の回答 (5)
- graphaffine
- ベストアンサー率23% (55/232)
supremacistさん、おはようございます。 タイトルからすると、行いたいのは近似計算ですよね。 そうすると、分子、分母とも15桁ですから答えの 有効数字も高々15桁です。従って、例え30桁求めても後ろ15桁は意味の無い数字になります。それでもよいから30桁求める事が目的だということでしたら、今までの回答を参考にしてください。(それらの方法を一般に多倍長計算といいます) 有効な15桁だけで良いということでしたら次のようになります。 double x = (double)428224593349304/136308121570117; xはdouble型ですので最大16桁が有効になります。
- neKo_deux
- ベストアンサー率44% (5541/12319)
i,jを渡して積kを得る処理、 // i*j=k seki(char *i, char *j, char *k); などを作成すると良いのでは? また、積の処理は和の処理と整数→文字列処理があると簡単な気がします。 // i+j=k tasu(char *i, char *j, char *k); // int→char変換 henkan(int i, char *j); -- > 友達は、428224593349304を1桁ずつ配列に入れて手計算でやるようにすればできると言っていたのですが できるけど、実は結構面倒だったりします。 オーバーフロー、アンダーフロー、小数、符号の処理など…。 1桁に1文字の方法ではありませんが、nビットの整数を考える「多倍長計算」というキーワードで情報収集すると良いかも。
- kary
- ベストアンサー率55% (10/18)
桁が多いので分かりやすくするために、42/19を考えます。 int i[2] = { 4, 2 }; int j[2] = { 1, 9 }; とします。まず、42の中に19が何個入るかを検討します。単純な方法としては19を1倍、2倍、...として、42を超えないもっとも大きい19の倍数を見つけます。10の位はj[0]×2=2です。1の位はj[1]×2=18で桁上りがありますので、j[0]++、j[1]=8とします。これで、19×2=38です。42-38は、10の位はi[0]=i[0]-j[0]=1です。1の位はi[1]=i[1]-j[1]=-4となり、かりが生じますので、i[0]--、i[1]=4となります。これで、42/19=2余り4が得られます。次はi[1]=4を10倍(i[0]=4、i[1]=0)して同様に計算します。筆算で割り算をすることを配列を使って表現するとこのようになると思います。 ご質問のように30桁の場合は30個+αの配列を用意すればいいと思いますし、それ以上の桁の計算もできます。 答えにはなっていないかも知れませんが、何かのご参考になれば幸いです。
- gimmick
- ベストアンサー率49% (134/270)
一番単純なのは以下のように1桁ずつ求める方法ではないでしょうか? 配列を使う必要もありません。ただし、桁数が多いので、64ビット整数型を 使うとよいでしょう。 428224593349304 / 136308121570117 = 3 余り 19300228638953 193002286389530 / 136308121570117 = 1 余り 56694164819413 566941648194130 / 136308121570117 = 4 余り 21709161913662 217091619136620 / 136308121570117 = 1 余り 80783497566503 807834975665030 / 136308121570117 = 5 余り 126294367814445 … 回答内容としては#1の方と同じです。
お礼
回答ありがとうございます。 参考にさせてもらいます。 今回は円周率を出したいのではなくて配列を使ったやり方を考えたいのでもう少し考えてみます。
- sha-girl
- ベストアンサー率52% (430/816)
小学校で習った割り算の筆算と同じ方法を 使えば何桁でもでると思います。 それが最良の方法かどうかは別にして 1桁づつ配列にいれれば可能です。
お礼
回答ありがとうございます。 1桁ずつ配列にいれて筆算と同じやり方で計算させる場合にはどのようにしたらいいのでしょうか? a[15]={4,2,8,2,2,4,5,9,3,3,4,9,3,0,4}; b[15]={1,3,6,3,0,8,1,2,1,5,7,0,1,1,7}; と確保して#3の方が言っているように 428224593349304/136308121570117=3 だからと計算させればいいのでしょうか? その場合最初に3と出すのは double x=428224593349304; double y=136308121570117; としておいてx/yから3を出すのでしょうか?
お礼
回答ありがとうございます。 >42の中に19が何個入るかを検討します というのは int i[2] = { 4, 2 }; int j[2] = { 1, 9 }; のほかに42と19を用意しとくのですか? 2個入ることがわかったとして j[0]=j[0]*2=2 j[1]=j[1]*2=18 として j[1]が桁上がりしているので j[0]++,j[1]=8として i[0]=i[0]-j[0]=1 i[1]=i[1]-j[1]=-6 として i[1]がマイナスなので1個上の位から持ってきて i[0]=0,i[1]=4となって 余りから計算するのに10倍して i[0]=4,i[1]=0として ここから19が何個入るかと考えるときは n=i[0]*10+i[1]として40を作らないといけないのでしょうか? またi[0],i[1]を10倍する前にi[0]が0じゃない場合はどのようにするのでしょうか?