2011-09-14 10 views
1

以下は、rand()関数の使用を習得したサンプルプログラムです。Cプログラミング - rand()の奇妙な出力

プログラムが実行されるたびに、rand()(プログラムの出力ではrand [0])によって生成された最初の数が〜と同じです。それは同じではありませんが、数字は常に最後に生成された数よりわずかに大きいだけです。 rand [1-4]は許容されるようにランダムに見える。誰が何が起こっているのか、そしてなぜそれを説明できますか?

は、この出力例で見てみましょう:

[[email protected] C] $ ./a.out 
rand[0]= 277735441     <<<?????? 
rand[1]= 1417591956 
rand[2]= 1284424674 
rand[3]= 819876274 
rand[4]= 1405457966 
[[email protected] C] $ ./a.out 
rand[0]= 277769055     <<<??????? 
rand[1]= 1982542454 
rand[2]= 234757526 
rand[3]= 642279943 
rand[4]= 1546192179 
[[email protected] C] $ ./a.out 
rand[0]= 277785862     <<<??????? 
rand[1]= 117534056 
rand[2]= 1857407599 
rand[3]= 1627223601 
rand[4]= 542817462 

ソースコードを:

/* 
    * rand: Generates 5 numbers using standard "srand()/rand()" function 
    * 
    * SAMPLE OUTPUT: 
    * rand[0]= 824522256 
    * rand[1]= 1360907941 
    * rand[2]= 1513675795 
    * rand[3]= 1046462087 
    * rand[4]= 253823980 
    */ 
    #include <stdio.h> 
    #include <stdlib.h> 
    #include <time.h> 

    int 
    main (int argc, char *argv[]) 
    { 
     /* Simple "srand()" seed: just use "time()" */ 
     unsigned int iseed = (unsigned int)time(0); 
     srand (iseed); 

     /* Now generate 5 pseudo-random numbers */ 
     int i; 
     for (i=0; i<5; i++) 
     { 
     printf ("rand[%d]= %u\n", 
      i, rand()); 
     } 
     return 0; 
    } 
+1

'rand'はかなり駄目で壊れています。私の理解は、これはクラスや何かのためのものです。ある日、擬似乱数を本当に使用する必要がある場合は、別のライブラリを探すようにしてください。 – zneak

答えて

0

randは、署名されたintを返します。これを符号なしの値として印刷しています。

+1

しかし 'rand'は常に正の整数を返すことが保証されているので、これは何の違いもありません。 – zneak

+0

intとして出力すると同じ結果になります。 –

+0

には、それぞれの最初の結果の類似点が説明されていません。 – fvu

4

共通の実装srandは、最初の乱数とその種子の相関が高くなります。この規格は、シーケンスがどれくらいランダムでなければならないかを保証しません。

+0

だから、 'srand'の後に' rand'をすることは勧められますか? –

+0

したがって、srand()が呼び出された後は、rand()によって生成された最初の数値を 'スローアウト'する必要があります?? rand()はこれをうまくやっていますか?間違っていますか?確かに私は何か間違っている。 –

+2

@yi_H(そして@Albert)、私は 'rand'を全く使わない方が良いと思います。このアルゴリズムは、不愉快なものとして広く認識されています。ほとんどのプラットフォームは、( 'random'関数、'/dev/random'仮想デバイスのような)より良いソリューションを提供します。まだ見つからなければ、[Mersenne Twister](http://www.math .sci.hiroshima-u.ac.jp /〜m-mat/MT/emt.html)ライブラリはかなり良い仕事をしています。 – zneak

0

基本的には、rand()は疑似ランダムジェネレータです。あなたがtime()を使ってシードしているので、それはおそらく数字が似ている理由です。

tv_sec * tv_usecなどの類似したgettimeofday()を使用してシードを試みます。

0

疑似ランダムジェネレータは決して真にランダムではありませんが、多種多様な数学的アルゴリズムに基づいています。私のシステムでは、一見合理的にシンプルなものがmanページごとに、使用されている:

static unsigned long next = 1; 

    /* RAND_MAX assumed to be 32767 */ 
    int myrand(void) { 
    next = next * 1103515245 + 12345; 
     return((unsigned)(next/65536) % 32768); 
    } 

    void mysrand(unsigned seed) { 
     next = seed; 
    } 

乱数発生器のこれらのタイプは、しばらくの間、回避されています。残りの算術に精通している場合は、開始値を取って32768を基準に余りにねじって回転させることがわかります。したがって、マシンが約束した範囲の値を取得します。これについては何も無作為です。あなたの価値は、あなたの次の数字の出発価値として使用されます。

あなたの場合、現在の時間をシードします。あなたのプログラムを十分に速く走らせれば、同じ値を得ることさえあります(それは起こるべきではありませんが、あなたの小さなプログラムをコンパイルして私のシステムで実行したときにはうまくいきました)。いずれにしても、もう一方を実行した後に速く実行すると、同様の値が表示される可能性が高くなります。

は、たぶんここに乱数生成をよく読んで:

http://en.wikipedia.org/wiki/Pseudorandom_number_generator

、それは少しより多くの意味を行います。

編集:あなたのシード値を乗算するために使用された定数をユーザが思いつくのに戸惑う場合、擬似ランダムジェネレータの品質は、結果値がランダムに見える'または' clustered '。真剣に良い擬似乱数が必要な場合(おそらく今はおそらくそうではないかもしれませんが)、自分で実装したいかもしれません。