web-dev-qa-db-ja.com

srandはRand関数とどのように関連していますか?

シード番号を変更しない場合、Rand()関数は、実行するたびに同じ番号を生成することを理解しています。それがsrand()の出番です。時間は常に変化するので、time(null)パラメーターをsrandに渡す必要があることを知っています。私の質問は、チュートリアルサイトの以下のコードです。

int main()
{
    int i, n=5;
    time_t t;

    /* Intializes random number generator */
    srand((unsigned) time(&t));

    /* Print 5 random numbers from 0 to 50 */
    for( i = 0 ; i < n ; i++ ) {
        printf("%d\n", Rand() % 50);
    }

    return(0);
}

ブランドからのリンクが表示されません

((unsigned) time(&t)); 

とランド。

printf("%d\n", Rand() % 50);

ランドとスランドの関係はどこにありますか?つまり、Rand()はsrand()から何らかのパラメーターを取得するため、毎回異なる数値を生成することを前提としています。私はそれがRand(srand(time(null));

それは、変数を使用せずに初期化するようなものです。 srandは初期化されていますが、使用されているようには見えません。

ランドはランドの前に最初に呼び出されるため、ランドは異なる数値を生成しますか?

18
Arrow

乱数シードはグローバルな静的変数です。 Randsrandの両方にアクセスできます。

21
sqykly

srand()は、Randによって使用されるシードを設定し、「ランダムな」数を生成します(通常は疑似乱数なので引用符で囲みます)。 srandを最初に呼び出す前にRandを呼び出さないと、srand(1)を呼び出してシードを1に設定したようになります。

多くのコードは現在の時刻をシードとして使用して、各プログラムが異なる乱数シーケンスを使用するようにしますが、デバッグ中に再現性の目的でいつでもsrand(42)のようなものに変更できます。そして、time()への呼び出しは実際には必要時間を入れる変数ではありません。単にNULLを渡すことができます:

_srand (time (NULL));
_

全体は、標準(_ISO C99 7.20.2.2 The srand function_)に示されている例のように、単一のファイルで実装できます。

_// Rand_MAX assumed to be 32767.
static unsigned long int next = 1;
void srand(unsigned int seed) { next = seed; }
int Rand(void) {
    next = next * 1103515245 + 12345;
    return (unsigned int)(next/65536) % 32768;
}
_

nextがファイルの先頭にある静的変数であるという事実は、ファイルの外側のすべてに対しては見えないが、内側のすべてに対しては見えることを意味します(ローカライズされたグローバルの一種)。これが、srand()Rand()の間の通信方法です。

13
paxdiablo

(幸運なことに)Rand()を設計した人は、stdioからFILEの中にあるものが見えないのと同じように、実装の詳細を保持することにしたので、リンクは表示されません。 ;欠点は、その状態をジェネレーターへのパラメーターではなく、グローバル(ただし非表示)変数にすることにしたことです。

これとは対照的に、非推奨のRand_r():状態は符号なし整数(> = 32ビットと想定)です。つまり、forbidden状態がそれよりも大きい、より良いジェネレーター、単にそれを格納するスペースがないからです!

代わりに、内部状態を非表示にしておくと、初期化なしでRandを呼び出すことがsrandを呼び出すことと同じであることが保証されている限り、最適なアルゴリズム(速度、周期など)を自由に選択して舞台裏で使用できますseed == 1で。

Paxdiabloは、C標準の例を示しました。 Rand/srandの後ろに隠すことができる別のジェネレーターを使用した例については、例えば http://en.wikipedia.org/wiki/Multiply-with-carry を参照してください。

余分に明確にするために:Rand_rが適切に設計されていれば、Rand_t(整数、構造、配列など)のような不透明な型があります。次のように、Rand_rといくつかの架空のsrand_rに渡します。

Rand_t state;
srand_r(&state, 1);
n = Rand_r(&state);

Rand関数は、state変数が1つしかないことを除いて、まったく同じです。

4
loreb

Randは、擬似乱数列を提供します。

この番号は、呼び出されるたびに明らかに関連のない一連の番号を返すアルゴリズムによって生成されます。このアルゴリズムはシードを使用してシリーズを生成します。このシリーズは、関数srandを使用して特定の値に初期化する必要があります。

srandは、呼び出し中のリスト内のある場所へのポインターを設定します。各試行で呼び出したり、与えたりしない場合修正シードを使用すると、同じシーケンスが得られます。多くの人が、現在の秒をシードとして与えることを提案しています。ただし、同じ秒でコードを2回実行すると、同じシーケンスが得られます。

Srandの呼び出しで使用されるすべての異なるシード値について、擬似乱数ジェネレーターは、R​​andの後続の呼び出しで異なる連続した結果を生成することが期待できます 詳細説明

0
Jimit Rupani