srandの推奨初期化方法について教えてください。
質問
C++で擬似乱数生成器を初期化するための「良い」方法が必要です。私が見つけたのは 記事 には、次のように書かれています。
乱数のようなものを生成するために を生成するために、srandは通常、初期化されます。 を、実行時間に関連するような特徴的な値に初期化します。 実行時間に関連した値です。例えば によって返される値は 関数time (ヘッダ ctimeで宣言されている)が返す値は,毎秒異なり,これは これは,ほとんどの ランダムの必要性には十分な特徴です。
Unixtimeは私のアプリケーションにとって十分に特徴的ではありません。これを初期化するためのより良い方法は何でしょうか?移植可能であればボーナスポイントがありますが、コードは主にLinuxホスト上で実行されるでしょう。
私は、intを得るためにいくつかのpid/unixtimeの計算を行うか、あるいはおそらく
/dev/urandom
.
ありがとうございます!
EDIT
はい、実際に1秒間に何度もアプリケーションを起動しており、衝突に遭遇しています。
どのように解決すればよいのでしょうか。
ベストアンサーは
<random>
. C++11以前のバージョンを使用している場合は、Boost乱数のものを見ることもできます。
しかし、もし私たちが
rand()
と
srand()
は
<ストライク
ベスト
最も簡単な方法は、単に
time()
:
int main()
{
srand(time(nullptr));
...
}
を呼び出すたびにではなく、必ずプログラムの冒頭で行うようにしてください。
rand()
!
サイドノート
ノート
: 以下のコメントで、これが安全でないことについての議論があります(これは真実ですが、最終的には関係ありません(続きを読む))。そこで代替案として、ランダムデバイスからシードする方法があります。
/dev/random
(または他の安全な本物の乱数生成器) を使うことです。
しかし
: この言葉に騙されてはいけません。これは
rand()
を使っているのです。たとえ見事に生成されたシードを使ったとしても、それは予測可能です(任意の値を持っていれば、次の値の完全なシーケンスを予測することができます)。これは生成する際にのみ有効で
"pseudo"
ランダムな値を生成する場合にのみ有効です。
もしあなたが安全であることを望むなら、あなたはおそらく
<random>
(を使うべきでしょう(ただし、私はセキュリティに詳しいサイトでもう少し読みます)。出発点として、以下の回答を参照してください。
https://stackoverflow.com/a/29190957/14065
をご覧ください。
二次的な注記: ランダムなデバイスを使用することは、実際には、以下の私のオリジナルの提案よりも、1 秒間に複数のコピーを開始する問題を解決します (セキュリティの問題だけではありません)。
元のストーリーに戻る。
起動するたびに、time() は一意な値を返します (アプリケーションを 1 秒間に何度も起動しない限り)。32ビットシステムでは、60年ごとくらいにしか繰り返されません。
あなたは時間が十分にユニークでないと思っているようですが、私はそれを信じるのは難しいと思っています。しかし、私は間違っていることが知られています。
もしあなたがアプリケーションの多くのコピーを同時に開始するのであれば、より細かい解像度のタイマーを使用することができます。しかし、その場合、値が繰り返されるまでの期間が短くなる危険性があります。
OK、では、本当に1秒間に複数のアプリケーションを起動していると考えるなら。
それなら、タイマーの粒を細かくして使ってください。
int main()
{
struct timeval time;
gettimeofday(&time,NULL);
// microsecond has 1 000 000
// Assuming you did not need quite that accuracy
// Also do not assume the system clock has that accuracy.
srand((time.tv_sec * 1000) + (time.tv_usec / 1000));
// The trouble here is that the seed will repeat every
// 24 days or so.
// If you use 100 (rather than 1000) the seed repeats every 248 days.
// Do not make the MISTAKE of using just the tv_usec
// This will mean your seed repeats every second.
}
関連
-
[解決済み】C++コンパイルタイムエラー:数値定数の前に期待される識別子
-
[解決済み】致命的なエラー LNK1169: ゲームプログラミングで1つ以上の多重定義されたシンボルが発見された
-
[解決済み】エラー:不完全な型へのメンバーアクセス:前方宣言の
-
[解決済み】 while(cin) と while(cin >> num) の違いは何ですか?)
-
[解決済み】Enterキーを押して続行する
-
[解決済み] to_string は std のメンバーではない、と g++ が言っている (mingw)
-
[解決済み] C++でintをstringに変換する最も簡単な方法
-
[解決済み] std::vectorをハードコードされた要素で初期化する最も簡単な方法は何ですか?
-
[解決済み] C++で静的プライベートメンバを初期化する方法は?
-
[解決済み] srand() - なぜ一度しか呼ばないのか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】コンストラクターでのエラー:識別子を期待されますか?
-
[解決済み】非静的メンバ関数への参照を呼び出す必要がある
-
[解決済み】 != と =! の違いと例(C++の場合)
-
[解決済み] string does not name a type Errorが発生するのはなぜですか?
-
[解決済み】c++でstd::vectorを返すための効率的な方法
-
[解決済み】「std::operator」で「operator<<」にマッチするものがない。
-
[解決済み】指定範囲内の乱数で配列を埋める(C++)
-
[解決済み] 解決済み] `pthread_create' への未定義の参照 [重複] [重複
-
[解決済み】C++ - 適切なデフォルトコンストラクタがない [重複]。
-
[解決済み】Eclipse IDEでC++エラー「nullptrはこのスコープで宣言されていません」が発生する件