円周率の値を求める方法とは?

このQ&Aのポイント
  • 円周率の値を求める方法について質問があります。Nを大きくすると3.1415に近づくはずですが、うまくいきません。解決策を教えてください。
  • 円周率の値を求めるプログラムを実行して、結果が得られました。Nの値を10から1000000まで変化させた結果、それぞれに対する近似値が表示されました。
  • Nの値を大きくすると、円周率の近似値が徐々に3.1415に近づいていくことが分かります。しかし、どのような問題があるのか具体的にはわかりません。
回答を見る
  • ベストアンサー

円周率 πの値

円周率πの値を求めたのですがNを大きくすると3.1415・・・に近づくはずですが、うまくいきません。どうすればいいのか検討がつきませんので、ご指摘お願いします。 float myrand() { float ans; ans=(float)rand()/(RAND_MAX); return(ans); } main() { int i,sum; long N; float ans,x,y,r,p; srand((unsigned)time(NULL)); sum=0; for(N=10;N<=1000000;N*=10){ for(i=10;i<N;i++){ x=myrand(); y=myrand(); r=x*x+y*y; if(r<=1){ sum++; } } ans=(float)(sum)/N; p=ans*4; printf("%d %f\n",N,p); } getch(); exit(0); } 実行結果 10 0.000000 100 2.640000 1000 3.440000 10000 3.483600 100000 3.490640 1000000 3.491268

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

  • ベストアンサー
  • tatsu99
  • ベストアンサー率52% (391/751)
回答No.5

このソースをよく検討してみると(見当ではありません)、以下の2箇所を直せばよいことがわかります。 おかしいのは、以下のところです。 sum=0;  ・・ここでクリアしてはいけない。 for(N=10;N<=1000000;N*=10){ for(i=10;i<N;i++){ ・・i=10 ではなく、i=0とする。 従って、以下のようにします。 srand((unsigned)time(NULL)); for(N=10;N<=1000000;N*=10){ sum=0;       ・・・・・・・・ここでクリアする for(i=0;i<N;i++){  ・・・・i=0にする 上記のようにして実行してみて下さい。 ほぼ望んだ結果になります。

その他の回答 (4)

  • Oh-Orange
  • ベストアンサー率63% (854/1345)
回答No.4

★アドバイス >円周率πの値を求めたのですがNを大きくすると3.1415・・・に近づくはずですが、うまくいきません。  ↑  擬似乱数を使っているので上手くいくときとそうでない場合があるからでしょう。  それかfloat型よりもdouble型の方が有効桁数が多い分だけ精度が出ませんか?  あるいはNをかなり大きくしないと精度がでないとか? ・私もちょっと作ってみました。  私は unsigned long long 型で試しました。 サンプル: #include <time.h> #include <stdio.h> #include <stdlib.h> // ベース定数 #define BASE 1000000000LL // 擬似乱数 unsigned long long myrand( void ) {  return ((unsigned long long)rand() * rand() * rand() * rand()) % BASE; } // メイン関数 int main( void ) {  unsigned long N, pi, i, sum;  unsigned long long x, y, r;    srand( (unsigned)time(NULL) );    for ( N = 10 ; N <= 10000000 ; N *= 10 ){   for ( sum = i = 0 ; i < N ; i++ ){    x = myrand();    y = myrand();    r = (x * x) + (y * y);        if ( r < (BASE * BASE) ){     sum++;    }   }   pi = (sum * 4);   printf( "%8lu %lu\n", N, pi );  }  return 0; } 実行結果(例): 10 32 100 332 1000 3148 10000 31364 100000 314236 1000000 3143132 10000000 31415956 4回実行したうちの1つです。 最初に実行した時間が精度が良かったみたいです。 覚えていませんが…。

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.3

処理系によるところもあるんだけど, もっとまともな疑似乱数発生器使ってみるとか.

  • asuncion
  • ベストアンサー率33% (2126/6286)
回答No.2

ぜい肉を少しそぎ落としてみました。 ついでに、 × 検討がつきません ○ 見当がつきません #include <stdio.h> #include <stdlib.h> #include <time.h> double myrand(void) {   return (double) rand() / RAND_MAX; } int main(void) {   int i, sum, n;   double x, y;      srand((unsigned) time(NULL));   for (n = 10; n <= 1000000; n *= 10) {     for(sum = i = 0; i < n; i++) {       x = myrand();       y = myrand();       if (x * x + y * y < 1.0)         sum++;     }     printf("%d %f\n", n, 4.0 * sum / n);   }   return 0; } (注)インデントのため、全角空白を使っています。

  • Werner
  • ベストアンサー率53% (395/735)
回答No.1

> for(i=10;i<N;i++){ このループの開始時にsumが0になっていません。 (なぜiが10から始まるのかも疑問だが。) あと、Nがlongなのにiやsumがintでいいの?

関連するQ&A

  • 精度を上げたいのですが…

    #include <stdio.h> #include <time.h> #include <stdlib.h> #define MAX 1000 main(void) { int i; float x1, x2, en, sum=0.0, s; srand( (unsigned)time( NULL ) ); for(i=0;i<MAX;i++) { x1=((float)rand()/(float)RAND_MAX); x2=((float)rand()/(float)RAND_MAX); if(en=(x1-0.5)*(x1-0.5)+(x2-0.5)*(x2-0.5)<=(0.5)*(0.5)) { sum++; } } s=sum/MAX; printf("円の面積:%15.6e\n",s); } この方法で円の面積を求めたんですが、もう少し精度を上げたいと思います。ただそのプログラムをどうやって書けばいいのかさえわからずとまどっています。円全体でなくその一部を考え、またその部分を簡単に面積が求められるようにわけるプログラムを組みたいのですがどのようにすればいいのか教えてください。

  • この円を分割して。。

    #include <stdio.h> #include <time.h> #include <stdlib.h> #define MAX 10000 void main(void) { int i; float x1, x2, en, sum=0.0, s; srand( (unsigned)time( NULL ) ); for(i=0;i<MAX;i++) { x1=((float)rand()/(float)RAND_MAX); x2=((float)rand()/(float)RAND_MAX); if(en=(x1-0.5)*(x1-0.5)+(x2-0.5)*(x2-0.5)<=(0.5)*(0.5)) { sum++; } } s=sum/MAX; printf("円の面積:%15.6e\n",s); } 円の面積を求める方法です。がもう少し精度をあげる工夫をしようと思うのですが、円を4分割した第一象限の部分に乱数をとばしその面積を求め、4倍することで求めたいのですがどうプログラムを変えたらいいか教えてください。

  • Visial C++おけるπの使い方

    自宅でCプログラミングの練習をするためVisial C++ 2008を使って プログラムをしています。y<sin(πx)となった時の 割合などを計算するプログラムで                「M_PIが定義されていない識別子です」 とでてきます。所持している本を参考にしてもM_PI=πとして用いる と書いてあり、math.hもインクルードしてるので原因が分からなくて 困ってます。Visial c++ではπの使い方には何か別の使い方がある のでしょうか?よろしくお願いします。 *↓が実際に作ったプログラムです。 #include <stdio.h> #include <stdlib.h> #include <time.h> #include <math.h> int main(void){ int i,n,count=0; double x,y,r,error; srand((unsigned)time(NULL)); /*乱数の初期化*/ printf("How many trials?"); scanf("&d",&n); for(i=0;i<n;i++){ x=rand()/(RAND_MAX+1.0); y=rand()/(RAND_MAX+1.0); if(y<sin(M_PI*x)){ count++; } } r=(double)count/n; /*キャスト演算子を使用*/ error=2/M_PI-r; printf("Result is %f (Error: %f)\n",r,error); return 0; }

  • 次のプログラムは、円周率だの近似値を求めるプログラムである。プログラム

    次のプログラムは、円周率だの近似値を求めるプログラムである。プログラム中の○に適するものを記入しなさい。 これを教えてください! C言語です #include<stdio.h> void main(void) { int sei,en; float pai,x,y,r; r=1.0; sei=0; en=0; for(x=0,1;○;x=x+0,1){ for(y=0.1;y<=1.0;○){ sei=sei+1; if((x*x+y*y)<=r*r)en=○; } } pai=(4.0*○)/(float)sei; printf("円周率=○¥n",pai); }

  • 型変換??

    int RANDOM_FUNCTION( int n ) { return (int)( rand() / (float)RAND_MAX * n ); } について Q1.この関数は0からn-1までの乱数を作るそうなのですが,何故ですか? 0<=rand()<=RAND_MAX だから0からnまでの乱数ができるような気がするのですが. Q2.RAND_MAXではなく(float)RAND_MAXとキャストしてある意味は何ですか? Q3.srand((unsigned)time(NULL));と srand((unsigned int)time(NULL));では何か違いますか? Q4.  static int first = 0; if (first == 0){ srand((unsigned)time(NULL)); first = 1; } という処理でsrand((unsigned)time(NULL));は最初の一回だけ呼び出されるようになっているようですが,この部分を srand((unsigned)time(NULL)); というように毎回呼び出すようにするとどうなりますか? 一回呼び出すだけで乱数系列の初期値が呼び出される時に変化しているのですか? Q5.この関数とは関係ない質問ですが,例えば a:int型 b:int型 c:double型 d:float型 のとき d = a / b + c という演算は 1 a:int型,b:int型より(a / b)の結果はint型(小数になった場合は小数点以下切り捨て) 2 (a / b):int型,c:double型,int<doubleより (a / b + c)の結果はdouble型 3 d:float型,『=のあるときは左辺の型に合わせる』よりdはfloat型 というように型変換されているという解釈でいいのでしょうか??

  • モンテカルロ法を用いた実験

    モンテカルロ法を用いてy=x^2とx軸で囲まれた部分の面積の近似値を求める.これを利用して平均μ,標準偏差σ,を求めたところ下記の写真のようになった.点数nに対して標準偏差は何次であるかを,中心極限定理から求められる次数,実験結果から導かれる次数のそれぞれで求めなさい.次数とはどのように求められるのでしょうか?使用したプログラムを下に書いておきます. #include <stdio.h> #include <time.h> #include <stdlib.h> #include <math.h> double f(double x); int main(void) { int M = 1000; int i,j,n,c,k; int tmp[6] = { 20, 50, 100, 200, 500, 1000 }; double x,y,Y, sumY, sumY2, muY, muY2, sigmaY; srand((unsigned int)time(NULL)); for (k = 0; k < 6; k++){ sumY = 0; sumY2 = 0; for (j = 0; j < M; j++){ c = 0; n = tmp[k]; for (i = 0; i < n; i++){ x = (1.0* (double)rand()) / ((double)RAND_MAX + 1.0); y = (1.0* (double)rand()) / ((double)RAND_MAX + 1.0); if (y <= f(x)){ c++; } } Y = ((double)c) / (double)n; sumY = sumY + Y; sumY2 += Y*Y; } muY = sumY / (double)M; muY2 =sumY2 / (double)M; sigmaY = sqrt(muY2 -(muY*muY)); printf("%d %lf %lf\n", n, muY, sigmaY); } return 0; } double f(double x) { double r = x * x; return r; }

  • char→10進数

    PICのプラグラムをC言語で書いています。 unsigned charでxを宣言して、xには電圧をAD変換した値(8bit)が代入されます。このxの値を10進数に変換したいのですが、char型をどうすればint型に変換すればいいのか分かりません。 自分なりに作ってみましたが、うまく動作しません。ご教授よろしくお願いします。 /*抜粋*/ unsigned char x; int y,i; float n; ・・・ y=0; for(i=7;i>=0;i--){   n=(((x>>i)<<7)>>7);   if(n==1)n=pow(2,i);   y=y+(int)n; }

  • C言語のプログラムでおかしな動作をするのですが教えて頂けないでしょうか?

    VisualStudio2008使用しています。 問題は、サイコロを200回振ってその出た目の数の個数分*を表示するプログラムです。 サイコロの目はランダムで出しています。 次のプログラムは正常に動作するものです。 /* #include <stdio.h> #include<stdlib.h> #include<time.h> #define N 200 int DICE(int min,int max); int main() { int n,i,j; int y[7]={0}; srand((unsigned int)time(NULL)); for(i=0;i<N;i++){ n=DICE(1,6); y[n]++; } for(i=1;i<7;i++){ printf(" %2d: ",i); for(j=0;j<y[i];j++){ printf("*"); } printf("\n"); } return 0; } int DICE(int min,int max) { return min+(int)(rand()*(max-min+1.0)/(1.0+RAND_MAX)); } */ 次のプログラムが問題で、授業で先生が配列にはstaticをおまじないとしてつけないと暴走すると言われたので、つけて見ると明らかに間違ってると思われるプログラムで動作するのですが原因を教えて頂けないでしょうか? 以下問題のプログラム! 配列の前にstaticをつけたら、添え字をいくつにしても正常に動作します。普通は添え自分しか領域って確保されないですよね??? /* #include <stdio.h> #include<stdlib.h> #include<time.h> #define N 200 int DICE(int min,int max); int main() { int n,i,j; //以下が問題の配列宣言 static int y[2]={0}; srand((unsigned int)time(NULL)); for(i=0;i<N;i++){ n=DICE(1,6); y[n]++; } for(i=1;i<7;i++){ printf(" %2d: ",i); for(j=0;j<y[i];j++){ printf("*"); } printf("\n"); } return 0; } int DICE(int min,int max) { return min+(int)(rand()*(max-min+1.0)/(1.0+RAND_MAX)); } 質問の意味が正確に伝わらなかった場合は補足しますので、ご回答よろしくお願いします。

  • 初心者の作ったプログラムの問題点を指摘ください。

    下のように、0から9までの乱数の発生回数の標準偏差を求めるプログラムを組んでみたのですが、最後のシグマの演算が無視されてしまい、0.000000と出力されてしまいます。どこがいけないのでしょうか? #include<stdio.h> #include<time.h> #include<stdlib.h> #include<math.h> int main (void){ int N,i,j,r,a[10]={0,0,0,0,0,0,0,0,0,0}; double S=0; printf("How many trials?;"); scanf("%d",&N); srand((unsigned)time(NULL)); /*初期化*/ for(i=0;i<N;i=i+1) { r=(int)(rand()/(RAND_MAX +1.0)*10); /*乱数N個取得*/ a[r]=a[r]+1; } for(r=0;r<10;r=r+1){ printf("a[%d]=%d.\n",r,a[r]); S=1/10*(S+sqrt((a[r]-N/10)*(a[r]-N/10)));  /*演算(無視されてしまう・・・)*/ } printf("Sigma=%f",&S); return 0; }

  • 関数の出力引数をクラスにするには?

    既出、または基礎の質問でしたらすみません。 ここでも他の検索エンジンでも見つけられなかったので。。。 C++です。 クラスを出力する関数を作りたいのですが、うまくできません。 ソースは以下のとおりです。問題は、プログラム下方のf1(),f2(),main()です。 長くて、そして見づらくてすみません・・・ //////////// #include<stdio.h> class test{ private: int num; float *vec; public: test(int n=1); //ctor ~test(); //dtor int getnum(){return num;} float* getvec(); void set(int,float*); void show(); }; test::test(int n){ num = n; vec = new float[n]; for(int i=0; i<n; i++) vec[i] = (float)i; } test::~test() {delete[] vec;} float* test::getvec(){ float *v; v = new float[num]; for(int i=0; i<num; i++) v[i] = vec[i]; return v; } void test::set(int n, float *v){ num = n; vec = new float[n]; for(int i=0; i<n; i++) vec[i] = v[i]; } void test::show(){ for(int i=0; i<num; i++) printf("%d: %g\n",i,vec[i]); } void f1(test &x, test &y){ int n; float *v; n = x.getnum(); v = x.getvec(); for(int i=0; i<n-1; i++) v[i] = 2.0*v[i]; y.set(n-1,v); } test f2(test x){ test y; //* int n; float *v; n = x.getnum(); v = x.getvec(); for(int i=0; i<n-1; i++) v[i] = 2.0*v[i]; y.set(n-1,v); return y; //** } void main(){ test x,y; int n = 4; float v[4] = {1.0,2.0,3.0,4.0}; printf("x:\n"); x.set(n,v); x.show(); printf("f1:\n"); f1(x,y); y.show(); printf("f2:\n"); y=f2(x); y.show(); } //////////// これを実行すると x: 0: 1 1: 2 2: 3 3: 4 f1: 0: 2 1: 4 2: 6 f2: 0: 7.38979e-38 1: 7.38979e-38 2: 6 となります。 関数f2がうまく動かない理由がわかりません。。。 出力引数にクラスはとれないのでしょうか?? よろしくお願いします。

専門家に質問してみよう