18

srand(1)C(++)のPRNGを(参照srandで定義されているように)への呼び出し前の状態にリセットする難しい方法を見つけました。ただし、シード 0 は同じように見えるか、呼び出し前の状態がシード 0 を使用しているように見えます。これら 2 つの呼び出しの違いは何ですか、またはそれらが同じことを行う理由は何ですか?srand

たとえば、このコード ( Ideone で実行)

#include <stdio.h>
#include <stdlib.h>

int main() {
    for (int seed = 0; seed < 4; seed++ ) {
        printf( "Seed %d:", seed);
        srand( seed );
        for(int i = 0; i < 5; i++ )
            printf( "    %10d", rand() );
        printf( "\n");
    }
    return 0;
}

戻り値

Seed 0:    1804289383     846930886    1681692777    1714636915    1957747793
Seed 1:    1804289383     846930886    1681692777    1714636915    1957747793
Seed 2:    1505335290    1738766719     190686788     260874575     747983061
Seed 3:    1205554746     483147985     844158168     953350440     612121425
4

7 に答える 7

19

glibc のやり方:

関数内の glibc/stdlib/random_r.c の 181 行目あたり__srandom_r

  /* We must make sure the seed is not 0.  Take arbitrarily 1 in this case.  */
  if (seed == 0)
    seed = 1;

しかし、これが glibc のやり方です。C 標準ライブラリの実装に依存します。

于 2011-11-08T11:44:17.140 に答える
12

それはおそらく実装の詳細です。標準では、ランダム シード 1 が特別であることが義務付けられており、特定のランダム ジェネレータ アルゴリズムの内部レジスタはおそらくゼロで初期化されているため、シード(0) とシード(1) で同じランダム シーケンスが発生します。あなたの srand() 実装の最初の行が次のようになっていることに賭けてもいいでしょう:

if ( seed == 1 ) seed = 0;

標準に準拠した動作を強制します。

通常、rand() および srand() の乱数ジェネレーターは、異なるシードに対して異なるシーケンスを提供する必要はありませんが、同じシードに対して同じシーケンスを提供する必要はありません。したがって、異なるシードが異なる乱数シーケンスを生成することに依存しないでください。問題はありません。そうでない場合は、実装固有の楽しみへようこそ。

于 2011-11-08T11:23:38.390 に答える
7

C 標準も C++ 標準も、 と の実装の詳細についてはあまり述べていませrand()srand()。詳細はほぼ完全に実装者に委ねられています。C 標準では、次のことが要求されます。

その後、srand が同じシード値で呼び出された場合、疑似乱数のシーケンスが繰り返されます。srand の呼び出しが行われる前に rand が呼び出された場合、シード値 1 で srand が最初に呼び出されたときと同じシーケンスが生成されます。

ただし、異なるシードが異なるシーケンスを生成する必要があるという要件は含まれていません。どうやら、あなたのシステムでは、0 と 1 のシードは同じ効果があります。srand(0)これは、PRNG を初期状態にリセットすることを期待するソフ​​トウェアとの下位互換性を提供するためだと思います。

于 2011-11-08T11:23:02.130 に答える
1

seedが1に設定されている場合、ジェネレーターは初期値に再初期化され、randまたはsrandを呼び出す前と同じ値を生成します。srandリファレンスから取得

于 2011-11-08T11:26:54.177 に答える
0

srand()関数は、引数を、後続のrand()の呼び出しによって返される疑似乱数の新しいシーケンスのシードとして使用します。次に、同じシード値でsrand()が呼び出された場合、疑似乱数のシーケンスが繰り返されます。srand()の呼び出しが行われる前にrand()が呼び出された場合、シード値1でsrand()が最初に呼び出されたときと同じシーケンスが生成されます。

たぶん役に立つ: http: //pubs.opengroup.org/onlinepubs/009695399/functions/rand.html

于 2011-11-08T11:26:40.597 に答える
0

マニュアル ページを読むと、「シード値が指定されていない場合、rand() 関数は自動的に値 1 でシードされます」と記載されています。これがおそらく、リンク先のリファレンス ページに 1 でシードすると状態がリセットされると記載されている理由です。

0 と 1 の両方のシードで同じ結果が発生することは、実装に依存する可能性が最も高く、すべてのプラットフォームで発生すると見なされるべきではありません。

于 2011-11-08T11:23:55.860 に答える