7

2 つの質問があります。

  1. を使用せずに C++ で疑似乱数ジェネレーターをシードする他の方法はありsrand(time(NULL))ますか?

  2. 最初の質問をした理由。現在、ジェネレーターのシードとして時間を使用していますが、ジェネレーターが返す数値は常に同じです。その理由は、時間を格納する変数がある程度切り捨てられているためだと確信しています。(「暗黙の変換は整数の精度を失います:「time_t」(別名「long」)から「unsigned int」」という警告メッセージがあります)これは、本質的に私のシードが来年まで変更されないことを伝えていると推測しています私の目的では、時間をシードとして使用しても問題なく動作しますが、この警告を取り除く方法がわかりません。

以前にそのエラー メッセージが表示されたことがないので、Mac に関係があると思います。64 ビット OS X v10.8 です。私も Xcode を使用して記述とコンパイルを行っていますが、Xcode を使用している他のコンピューターでは問題はありませんでした。

編集:これをいじって調査した後、64ビットMacにあるバグを発見しました。(間違っていたら訂正してください。)time(NULL)シードとして 1 から 7 までの乱数を mac に選択させようとすると、常に 4 が得られます。いつも。mach_absolute_time()私はランダマイザーをシードするために使用することになりました。明らかに、これは私のプログラムからすべての移植性を排除します...しかし、私はただの趣味です。

Edit2:ソースコード:

#include <iostream>
#include <time.h>

using namespace std;

int main(int argc, const char * argv[]) {

srand(time(NULL));

cout << rand() % 7 + 1;

return 0;
}

このコードをもう一度実行してテストしました。現在は 3 しか返されていません。これは、C++ 自体ではなく、私のコンピューターに関係しているに違いありません。

4

4 に答える 4

11

Tl;dr ですが、おそらく、あなたのやり方は間違っています。次のようなものがあるかもしれませんが、シードは一度だけ設定する必要があります。

for ( ... )
{
   srand(time(NULL));
   whatever = rand();
}

いつあるべきか

srand(time(NULL));
for ( ... )
{
   whatever = rand();
}
于 2012-08-13T23:08:07.047 に答える
7

1.そうでもない。たとえば、ユーザーにランダムシードを入力するように求めることができます。または、他のシステム パラメータを使用しますが、違いはありません。

2.この警告を取り除くには、明示的な変換を行う必要があります。お気に入り:

unsigned int time_ui = unsigned int( time(NULL) );
srand( time_ui );

また

unsigned int time_ui = static_cast<unsigned int>( time(NULL) );

また

unsigned int time_ui = static_cast<unsigned int>( time(NULL)%1000 );

これが本当に変換の問題かどうかを確認するには、時間を画面に出力して自分自身を確認するだけです

std::cout << time(NULL);
于 2012-08-14T00:18:52.293 に答える
5

プログラムの最初に random が 1 回表示されるはずです。

int main()
{
    // When testing you probably want your code to be deterministic
    // Thus don't see random and you will get the same set of results each time
    // This will allow you to use unit tests on code that use rand().
    #if !defined(TESTING)
    srand(time(NULL));  // Never call again
    #endif

    // Your code here.

}
于 2012-08-14T00:05:07.703 に答える
0

x86 では、ライブラリ関数 TIME(NULL) の代わりに、CPU タイム スタンプ カウンターへの直接呼び出しをrdtsc使用できます。以下 1) タイムスタンプを読み取る 2) アセンブリ内のシード RAND:

rdtsc
mov edi, eax
call    srand

C++ の場合、以下は g++ コンパイラでジョブを実行します。

asm("rdtsc\n"
    "mov edi, eax\n"
    "call   srand");

注: ただし、コードが仮想マシンで実行されている場合はお勧めできません。

于 2016-04-13T20:55:32.243 に答える