- ベストアンサー
大きな数の乱数を作るには
- みんなの回答 (5)
- 専門家の回答
質問者が選んだベストアンサー
No.2の方が書かれているとおり、最初の積算で unsigned intの扱える値の範囲を超えて(オーバーフロー)しまっているものと思われます。 除算を先にすれば一応解決するはずです。 ul = (unsigned long)(4294967295.l * (rand() / (double)(RAND_MAX + 1))); ただ、環境にも依りますが rand()の精度が問題になりそうです。 RAND_MAXが 4294967295ならば問題はありませんが、それよりも小さな値の場合、0~4294967295の値の中の分解能が低くなるので、同じ値が出る確率が 1/4294967295よりも大きくなります。 (うちの VC7.1は RAND_MAXが 32767だったので、同じ値が出る可能性は 1/32767です) その確率を 1/4294967295にしたい場合は、例えば下記のように少し工夫が必要です。 int d = ULONG_MAX / RAND_MAX; int m = ULONG_MAX % RAND_MAX + 1; unsigned long ul = rand() * d + rand() % m;
その他の回答 (4)
- mac_res
- ベストアンサー率36% (568/1571)
スケーリングして拡大しても、隙間が空いてしまうので、2階建てにしたほうがよいと思います。 -- 8< -- 8< -- 8< -- 8< -- 8< -- 8< -- 8< -- 8< -- 8< -- 8< -- #include <stdio.h> #include <time.h> #include <stdlib.h> int main(void) { unsigned long long rnd; int cnt[100]; int i; srand(time(0)); for (i = 0; i < 100; i++) { cnt[i] = 0; } for (i = 0; i < 100000; i++) { rnd = (unsigned long long) rand() *RAND_MAX + rand(); cnt[(int)((double) rnd / RAND_MAX / RAND_MAX * 100)]++; } for (i = 0; i < 100; i++) { printf("%5d%10d\n",i, cnt[i]); } return 0; }
補足
ちょっと私には難しいですが、徐々に理解していこうと思います。 回答ありがとうございます。
- nofutureforyou
- ベストアンサー率9% (25/277)
C初心者なのになぜそんなことがしたいのかが疑問。
補足
仕事上必要になったもので・・・。 今まではVBを使っていましたが、今回Cで書かざるを得なくなりました。
- Tacosan
- ベストアンサー率23% (3656/15482)
思ったことその1: かけ算のところでオーバーフローする可能性があります. その2: そんな広い範囲にするために rand を使うのは無謀です. 別の関数を探すべし.
補足
回答ありがとうございます。 ご指摘の通り、オーバーフローを起こしているようです。 ul = 4294967295UL * rand() / (RAND_MAX + 1); を ul = 4294967295UL * (rand() / (RAND_MAX + 1.0)); に直したところ、うまくいきました。 1の部分も1.0でないとまずいようです。
- pi8027
- ベストアンサー率11% (6/53)
srand()とtima.hを使うんじゃないか?
補足
回答ありがとうございます。 srand(time(NULL)); を追加して実行しても値が変わりませんでした。
関連するQ&A
- 高精度乱数関数
rand()の値をRAND_MAX+1で割ると、[0, 1)の範囲になりますよね。 もし、RAND_MAX+1が2の乗数なら、浮動小数において結果は丸め誤差を含んでいないはずですよね。 unixのgccでコンパイルしたのですが、RAND_MAXの値は32767だったので、 #define (RM RAND_MAX + 1) #define RND ((long double)rand()) long double x; x = RND / RM + RND / RM / RM + RND / RM / RM / RM + RND / RM / RM / RM / RM ・ ・ ・; とすれば、精度の高い[0, 1)区間の乱数関数を作ることはできますか? この論理に間違いがあれば指摘してください。
- ベストアンサー
- C・C++・C#
- 乱数について・・・
(1)1,2,3,4の整数のどれかを乱数で発生させる方法 (2)0~1までの実数を発生させる方法 を教えていただけないでしょうか?(a.outするたびに値が変わってほしいです。) ※一応、下のプログラムにあるように実行するたびに違う乱数がanswerに入るようにはできたのですが、いまいち理解できていません。軽い説明や参考URLなども教えてもらえたら助かります。 よろしくお願いします。 #include<time.h> int main() { unsigned short time_a,time_b; unsigned long answer; time_a = time(NULL); time_b = time_a; srand(time_b); answer = rand(); printf("答えは = %d\n",answer); }
- ベストアンサー
- C・C++・C#
- 乱数について
乱数の分布を見るために以下のようなプログラムを書きました。 #include <stdio.h> #include <stdlib.h> #include <math.h> int main() { int i,imax, S[RAND_MAX], r; double x,y; FILE *output1; output1=fopen("random2.data","w"); imax=100000; for(i=0;i<=imax;i++){ r = rand(); S[r] += 1; } for(i=0;i<=RAND_MAX;i++){ fprintf(output1,"%d %d \n",i,S[i]); } return 0; } するとコンパイルできて実行もできるのですが、なぜか乱数が30000を 超えるくらいのところでおかしな値になりました。 原因がわからないのでどなたか教えてください。
- ベストアンサー
- C・C++・C#
- 乱数について(C言語)
C言語において,乱数の範囲を 0 ≦ r < 1 とする場合には double r=(double)rand()/(RAND_MAX+1); とするのは知っているのですが0 < r ≦ 1にする場合の方法がわからず困っています. アドバイスいただきたいです.
- ベストアンサー
- その他(インターネット・Webサービス)
- 毎回違う乱数を生成するにはどうしたらいいでしょうか
C言語の初心者です。よろしくお願いいたします! 乱数に関する質問:毎回違う乱数を生成するにはどうすればいいでしょうか。 学校の講義の中に >>time() は1970 年1 月1 日0 時0 分(標準時)からの経過秒数を返 すため,1 秒以内に何度も実行すると,同じ数字で乱数を初期化す ることになり,結果も同じになってしまう. という記述がありますが、時間を置いてから、実行しても同じ結果となりました。 その一 #include <stdio.h> #include <stdlib.h> #include <math.h> #include <time.h> int main(void) { double x,y; int i,index=0; double a,n; printf("How many trials?..."); scanf("%lf",&n); for (i=0;i<n;i++) { x=rand()/(RAND_MAX+1.0); y=rand()/(RAND_MAX+1.0); if((x*x+y*y)<1) index++;} a=4*index/n; printf("Result is %.2f(%.2f)",a,sin(-a)); return 0; } その二 #include <stdio.h> #include <stdlib.h> #include <time.h> int main(void) { int a; srand((unsigned)time(NULL)); a=(int)(rand()/(RAND_MAX+1.0)*10); printf("%d\n",a); return 0; } お忙しい中、教えていただけたらうれしいです。
- ベストアンサー
- その他([技術者向] コンピューター)
- 標準正規分布の乱数
RAND()関数は ((double)rand() / (1.0 + RAND_MAX))と定義します。 中心極限定理により、一様乱数を足し合わせると正規分布に近づくことから、 x = 分散 * (Σ[1~12]RAND() - 6) + 平均 で正規乱数が作れる。標準正規分布は分散1、平均0なのでその乱数は x = Σ[1~12]RAND() - 6 ですよね。この乱数を例えば100個羅列するにはどうしたらいいのでしょうか? もし間違ってたら指摘してください。 参考文献「Cによるシミュレーションプログラム 石川宏」 #include <stdio.h> #include <stdlib.h> #define RAND() ((double)rand() / (1.0 + RAND_MAX)) #define NUMBER 10000 /* 発生させる乱数の数 */ main(void) { int j; double u, x; srand(5); for (j = 0; j <= 11; j++) { u = u + RAND(); } x = u - 6.0; }
- ベストアンサー
- C・C++・C#
- 乱数について
Visual Studio2008を使っています。 #include<stdio.h> #include<stdlib.h> #include<time.h> int main(void){ int i; srand(time(NULL)); i=rand(); printf("%d\n",i); return 0; } 乱数を作るために上のようなプログラミングを作りました。 これを「ソリューションのビルド」すると 【warning C4244: '引数' : 'time_t' から 'unsigned int' への変換です。データが失われる可能性があります。】 と出ます。 このまま行っても乱数が出来るのですが どうしたらいいのでしょうか? 8行目を srand(time_t(NULL)); srand((unsigned)time(NULL)); と変えればいいのでしょうか? time_tでやると乱数が同じ値しか出てきません。 教えてください。
- ベストアンサー
- C・C++・C#
補足
指摘の通り直したところ、精度があがったようです。 と言うのは、 ul = 4294967295UL * (rand() / (RAND_MAX + 1.0)); で出てくるulは、16進に直すと必ず e98dffff,3341ffff などfが4つ続く数字となりました。d,mを導入することで、それが解消されたようです。