2016-04-16 15 views
2

私はcppreference.comで、通常の分散型の乱数を生成するための例を見て、これを取得するためのコードを少しリファクタリングた:私はこれを実行するたびに乱数ジェネレータをシードする方法は?

しかし
#include <iostream> 
#include <random> 

struct MyNormalDistribution { 
    static double getRandomNumber(double mean,double std_dev){ 
     return std::normal_distribution<>(mean,std_dev)(MyNormalDistribution::generator); 
    } 
    private: 
     static std::random_device rand; 
     static std::mt19937 generator; 
}; 
std::random_device MyNormalDistribution::rand; 
std::mt19937 MyNormalDistribution::generator = std::mt19937(MyNormalDistribution::rand()); 

int main(int argc, char *argv[]) { 
    for (int t=0;t<10;t++){ 
     std::cout << MyNormalDistribution::getRandomNumber(0,10) << std::endl; 
    } 
} 

は、私は数字の同じシーケンスを取得します。いくつかのばかげたミスがあるのか​​、あるいはcppreferenceの例に適切なシードが含まれていないのでしょうか?

正しくシードするにはMyNormalDistribution

+4

http://en.cppreference.com/w/cpp/numeric/random/mersenne_twister_engine/seed –

+0

ほとんどのプラットフォーム/システムには、暗号で安全な疑似乱数ジェネレータ([CSPRNG](https://en.wikipedia) .org/wiki/Cryptographically_secure_pseudorandom_number_generator))、本当のRNGではなく、本質的に非決定論的です。それらはユーザによってシードされる必要はなく、システム放射能の発生に基づいて継続的にエントロピーが追加される。 – zaph

答えて

-1

一つは、現在の時刻と例えばジェネレータをシードすることができます

#include <iostream> 
#include <random> 

struct MyGenerator { 
    std::mt19937 gen; 
    static std::random_device rand; 
    MyGenerator() : generator(rand()){ gen.seed(time(0)); } 
}; 
std::random_device MyGenerator::rand; 
struct MyNormalDistribution { 
    static double getRandomNumber(double mean,double std_dev){ 
     return std::normal_distribution<>(mean,std_dev)(MyNormalDistribution::gen.gen); 
    } 
    private: 
     static MyGenerator gen; 
}; 
MyGenerator MyNormalDistribution::gen; 
+1

現在の時間はひどい種です。クロックが操作され、複数の処理がクロック解像度内で開始されると、同じシードなどが得られます。 'std :: seed_seq'への入力の一部として、現在の時刻はokです(より多くのソースと組み合わされる場合)。ジェネレータをシードするために使用されます。しかし生の時間を使って発電機を直接播種しないでください。 –

+0

@JesperJuhl私はそれを修正するために何をすべきですか?いくつかのオフセットを追加しますか? – user463035818

0

それはcppreference.comで書かれているように、 "問題は" あなたのstdである:: random_device:

STD: :random_deviceは、 の非決定論的なソース(例えば、ハードウェアデバイス)が の実装に利用可能でない場合に、 実装定義の疑似乱数エンジンに関して実装されてもよい。この場合、各std :: random_deviceオブジェクトは が同じ番号シーケンスを生成することがあります。

つまり、Linux OSを使用していて、カーネルに「CONFIG_HW_RANDOM」オプションが設定されていないと思います。代わりに、システムクロックなどの別のシード値ソースを使用することもできます。

auto seed = std::chrono::system_clock::now().time_since_epoch().count(); 
std::mt19937 generator {seed}; 
+0

あなたは私が得たコメントを読むことができるように私の答えを元に戻しました。私はそれを改善する方法を知らなかったので、それは削除され、削除されました。私は ''から 'time'を使いますが、それ以外の場合はあなたの答えに大きな違いはありません。 – user463035818

+0

btw Windows上に元のコードでシーケンスが繰り返されていました。 – user463035818

0

代わりのrandを使用するか、mt19937最もプラットフォーム/システム上で利用可能である暗号学的に安全な擬似乱数生成器(CSPRNG)を使用します。

真のRNGではありませんが、本質的に非決定論的です。それらはユーザによってシードされる必要はなく、システム放射能の発生に基づいて継続的にエントロピーが追加される。

+0

なぜこの質問が復活したのか分かりませんが、なぜなら、私の質問はあまり「良い」種子を求めているわけではありませんが、私はrngをどのようにシードするのか混乱していました。それはmt19937ジェネレータを使用しています)。 – user463035818

関連する問題