電子書籍の厳選無料作品が豊富!

円周率πの値を求めたのですが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

A 回答 (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にする

上記のようにして実行してみて下さい。
ほぼ望んだ結果になります。
    • good
    • 0

★アドバイス


>円周率πの値を求めたのですが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つです。
最初に実行した時間が精度が良かったみたいです。
覚えていませんが…。
    • good
    • 0

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

    • good
    • 0

ぜい肉を少しそぎ落としてみました。


ついでに、
× 検討がつきません
○ 見当がつきません


#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;
}

(注)インデントのため、全角空白を使っています。
    • good
    • 0

> for(i=10;i<N;i++){


このループの開始時にsumが0になっていません。
(なぜiが10から始まるのかも疑問だが。)

あと、Nがlongなのにiやsumがintでいいの?
    • good
    • 0

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