• ベストアンサー

大きな数の乱数を作るには

C 初心者です。 表題のように、unsigned longのスケールの乱数をつくりたいんですが、以下のように記述すると値がいつも同じになります。この理由と、正しく動作するにはどう直したらいいのか教えてください。 unsigned long ul; ul = 4294967295UL * rand() / (RAND_MAX + 1); 値は常に131071でした。

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

  • ベストアンサー
回答No.3

 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;

hibachi
質問者

補足

指摘の通り直したところ、精度があがったようです。 と言うのは、 ul = 4294967295UL * (rand() / (RAND_MAX + 1.0)); で出てくるulは、16進に直すと必ず e98dffff,3341ffff などfが4つ続く数字となりました。d,mを導入することで、それが解消されたようです。

その他の回答 (4)

  • mac_res
  • ベストアンサー率36% (568/1571)
回答No.5

スケーリングして拡大しても、隙間が空いてしまうので、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; }

hibachi
質問者

補足

ちょっと私には難しいですが、徐々に理解していこうと思います。 回答ありがとうございます。

回答No.4

C初心者なのになぜそんなことがしたいのかが疑問。

hibachi
質問者

補足

仕事上必要になったもので・・・。 今まではVBを使っていましたが、今回Cで書かざるを得なくなりました。

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

思ったことその1: かけ算のところでオーバーフローする可能性があります. その2: そんな広い範囲にするために rand を使うのは無謀です. 別の関数を探すべし.

hibachi
質問者

補足

回答ありがとうございます。 ご指摘の通り、オーバーフローを起こしているようです。 ul = 4294967295UL * rand() / (RAND_MAX + 1); を ul = 4294967295UL * (rand() / (RAND_MAX + 1.0)); に直したところ、うまくいきました。 1の部分も1.0でないとまずいようです。

  • pi8027
  • ベストアンサー率11% (6/53)
回答No.1

srand()とtima.hを使うんじゃないか?

hibachi
質問者

補足

回答ありがとうございます。 srand(time(NULL)); を追加して実行しても値が変わりませんでした。

関連するQ&A

  • 乱数の最大値

    C言語で0~Nまでの乱数を発生させる場合、 srand((unsigned) time(NULL)); rand()%N; とやりますよね。 このやり方だと、発生する乱数はRAND_MAX以下しかできません。 RAND_MAX以上の値を発生させるにはどうすればいいのでしょうか?

  • 高精度乱数関数

    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)区間の乱数関数を作ることはできますか? この論理に間違いがあれば指摘してください。

  • 乱数について・・・

    (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); }

  • 乱数について

    乱数の分布を見るために以下のようなプログラムを書きました。 #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言語で0~1の乱数を作成する部分を書いているのですが num[i] = rand()/(RAND_MAX+0.1); と書いてループさせています。 numはdouble型で定義しているのですがこれで実行すると桁数が下6桁まで表示されてしまいます。 欲しいデータは0.1、0.2・・・1.0までの0.1刻みのデータなのですが桁数を制限するにはどうすればいいのでしょうか?

  • 乱数について(C言語)

    C言語において,乱数の範囲を 0 ≦ r < 1 とする場合には double r=(double)rand()/(RAND_MAX+1); とするのは知っているのですが0 < r ≦ 1にする場合の方法がわからず困っています. アドバイスいただきたいです.

  • 毎回違う乱数を生成するにはどうしたらいいでしょうか

    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; } お忙しい中、教えていただけたらうれしいです。

  • 乱数について

    こんばんは。 何度も申し訳ありませんが、今回は乱数について教えてください。 LinuxでCを勉強しているんですが、 randで乱数を発生させることはできたんですが、 そのプログラムを何度実行させても 出てきた乱数は同じ値なんです。 プログラム内で例えば10こ乱数を発生させたとすると 違うものが出ます。 しかし、もう一度そのプログラムをはしらせると 前回と全く同じ並びで同じ数が出るのはどうしてでしょうか? 言ってる意味わかっていただけましたでしょうか? 宜しくお願いします。

  • 標準正規分布の乱数

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

  • 乱数について

    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でやると乱数が同じ値しか出てきません。 教えてください。

専門家に質問してみよう