2

これはこの質問に関連しています - C++での乱数生成...最初の数はあまりランダムではありません

#include <iostream>
#include <stdlib.h>
#include <time.h>
using namespace std;

int main()
{
srand((unsigned int)time(NULL));

cout << rand() / double(RAND_MAX) << endl;
cout << rand() / double(RAND_MAX) << endl;
cout << rand() / double(RAND_MAX) << endl;
cout << rand() / double(RAND_MAX) << endl;
cout << rand() / double(RAND_MAX) << endl;

return 0;
}

バイナリ (.exe) を何度も実行すると、最初の結果の最初の 3 つの数値は常に同じであることがわかります。たとえば、実行ごとに常に 0.54xxxxx です。

いいえ、これは、パターンがない場所にパターンを見つけたからではありません。また、各実行の間に数秒待つことも役に立ちません。

編集:最初の結果のみ、最初の 3 つの数字が同じです。残りは「ランダムに見える」です。また、ジェネレーターには srand() がシードされています (上記のコード サンプルの最初の行)。

4

1 に答える 1

6

のランダム性はrand標準で指定されていません。ほとんどのジェネレーターは、シードを使用して静的変数を初期化し、そこから次の値を計算します。これは、ランダムに「表示」される必要があります (もちろん、完全に決定論的です)。私の推測では、あなたのマシンの実装は静的変数の古い値を返します。これは最初のシードと同じです。(これには驚かされます。静的の新しい値を返すのが普通です。)

とにかく、それは実装の品質の問題です。(VC++11 でも同じことが見られますが、g++ ではそうではありません。)

編集:

シードの変化が返される最初の数値にどのように影響するかを確認するための簡単なテスト:

for ( int i = 1; i <= 10; ++ i ) {
    std::srand( i );
    std::cout << i << ": " << std::rand() << std::endl;
}

VC++11 での出力:

1: 41
2: 45
3: 48
4: 51
5: 54
6: 58
7: 61
8: 64
9: 68
10: 71

g++ 4.7.2 (CygWin バージョン) の場合:

1: 1481765933
2: 816048218
3: 150330503
4: 1632096437
5: 966378722
6: 300661007
7: 1782426941
8: 1116709226
9: 450991511
10: 1932757444

あなたはこれをコード ブロックの下の g++ で見ていると言っています: コード ブロックは、g++ が GNU ライブラリではなく Microsoft ライブラリを使用するように設定していると推測できます (一般的にはより良い解決策)。

とにかく、解決策は簡単です: ジェネレーターをシードするために現在使用している単一の行を次のように置き換えます。

std::srand( std::time( NULL ) );
std::rand();        // throw out first value...

また、比較的優れた乱数が必要な場合は、std::rand 完全に破棄して、C++11 でより厳密に定義されたジェネレーターを使用してください。(C++11 を使用していない場合は、Boost から取得できます。)

于 2013-07-11T16:30:33.823 に答える