2015-12-28 17 views
6

kullanarak tohum nasıl ayarlanır.C++ 11: C++ ile 11 yeni rastgele kütüphane, egzersiz am <random>

>a 
Uniform [0, 1): 0.131538 
>a 
Uniform [0, 1): 0.131538 
>a 
Uniform [0, 1): 0.131538 

Ben denir program farklı her seferinde tohum ayarlamak istiyorum: Ben defalarca bu çalıştırdığınızda

#include <iostream> 
#include <random> 
using namespace std; 
int main() { 
    default_random_engine eng; 
    uniform_real_distribution<double> urd(0, 1); 
    cout << "Uniform [0, 1): " << urd(eng); 
} 

her seferinde aynı çıktıyı verir: Aşağıdaki asgari program yazdım Böylece her seferinde farklı bir rasgele sayı üretilir. Tamamen karanlık rastgele seed_seq denilen bir özellik sağlar farkındayım, ama ben (cplusplus.com at) bunun açıklamasını bulabilirsiniz:

http://www.cplusplus.com/reference/random/seed_seq/

bir programı yeni üretmek zorunda konusunda tavsiye sevinirim Her çağrıldığında tohum: Daha basit daha iyi.

Benim platformu (ler):

  • Windows 7: Bir sözde rasgele sayı üreteci gelen öngörülemeyen sonuçlar elde etmek için TDM-GCC compiler

cevap

3
sahip noktası bir seed_seq entropi arttırmaktır

oluşturulan dizi. O rastgele cihazdan birden sayılarla başlatılıyor, sisteminizde bir random_device varsa tartışmasız o yapabilir. I rastgelelik bir artış, yani üretilen dizi entropi olduğunu düşünüyorum olmayan bir yalancı rasgele sayı üreteci bir sistemde. sistem rastgele cihazı yoksa

std::random_device r; 
    // std::seed_seq ssq{r()}; 
    // and then passing it to the engine does the same 
    default_random_engine eng{r()}; 
    uniform_real_distribution<double> urd(0, 1); 
    cout << "Uniform [0, 1): " << urd(eng); 

o zaman kullanabilirsiniz: Sistem daha sonra rastgele bir cihaz temin yaparsa

bu gibi kullanabilirsiniz: yaklaşımınız bu konuda Bina

random_engine

default_random_engine eng{static_cast<long unsigned int>(time(0))}; 
    uniform_real_distribution<double> urd(0, 1); 
    cout << "Uniform [0, 1): " << urd(eng); 

bir tohum olarak time(0) Eğer rastgelelik birden kaynağınız varsa gerçekten bunu (örneğin 2)yapabilirsiniz R1, r2, farklı rasgele aygıtlardır, örneğin, r1, r2, örn. Bir ısıl gürültü veya kuantum kaynak.

karıştırıp Nihayet

std::seed_seq seed{ r1(), static_cast<long unsigned int>(time(0)) }; 
    default_random_engine eng{seed}; 
    uniform_real_distribution<double> urd(0, 1); 
    cout << "Uniform [0, 1): " << urd(eng); 

maç olabilir Tabii, ben bir tek astar ile başlatmak istiyorum: Eğer ikinci hassasiyet sahip time(0) dert varsa

auto rand = std::bind(std::uniform_real_distribution<double>{0,1}, 
       std::default_random_engine{std::random_device()()}); 
    std::cout << "Uniform [0,1): " << rand(); 

sen üstesinden gelebilir bames23 below tarafından ilk belirlenmiş dönemden beri süre istenerek high_resolution_clock ya oynayarak bu:

static_cast<long unsigned int>(std::chrono::high_resolution_clock::now().time_since_epoch().count()) 

ya da belki sadece kod içindeki fazla yorum eklemek Could CPU rastgelelik

long unsigned int getseed(int const K) 
{ 

    typedef std::chrono::high_resolution_clock hiclock; 

    auto gett= [](std::chrono::time_point<hiclock> t0) 
    { 
     auto tn = hiclock::now(); 
     return static_cast<long unsigned int>(std::chrono::duration_cast<std::chrono::microseconds>(tn-t0).count()); 
    }; 

    long unsigned int diffs[10]; 
    diffs[0] = gett(hiclock::now()); 
    for(int i=1; i!=10; i++) 
    { 
     auto last = hiclock::now(); 
     for(int k=K; k!=0; k--) 
     { 
      diffs[i]= gett(last); 
     } 
    } 

    return *std::max_element(&diffs[1],&diffs[9]); 
} 
+0

Teşekkürler, g241. Default_random_engine'nin bir aramayı zamana dahil etmek üzere değiştirilmesinden sonra (0) program çıkışı deterministik değildir. – Argent

+0

@Argent, AFAIK Windows'da rastgele bir motor yoktur, zaman (0) ikinci hassaslıkla akımı geçerli hale getirir, böylece sonraki işlemler farklı şekilde ekilebilir ve hedefinize ulaşır. İkincisi, parçalıktır. Bu cevap sorununuzu çözerse lütfen kabul edin. – g24l

+0

Windows kesinlikle rasgele bir motora sahiptir; varsayılan, oldukça iyi rasgele sayıları üretmek için advapi32.dll çağrısını yapan RtlGenRandom kullanan rand_s() öğesini kullanır (kriptoya giden tüm yolun maliyeti olmadan). –

4
#include <iostream> 
#include <random> 

using namespace std; 

int main() { 
    std::random_device r;          // 1 
    std::seed_seq seed{r(), r(), r(), r(), r(), r(), r(), r()}; // 2 
    std::mt19937 eng(seed);          // 3 

    uniform_real_distribution<double> urd(0, 1); 

    cout << "Uniform [0, 1): " << urd(eng); 
} 

biz öngörülemeyen tohum ihtiyacı olan bir kaynak veri. 1biz bu amaçla bir std::random_device oluşturun. üzerinde bir yalancı rasgele sayı üreteci tohumlama için uygun olan bir forma random_device üretilen birkaç değerlerini birleştirmek için bir std::seed_seq kullanın. seed_seq beslenir daha önceden tahmin edilemeyen veri tohumlu motorun daha az tahmin edilebilir sonuçlar olacaktır. üzerinde motorunun başlangıç ​​durumunu tohumlamak için seed_seq kullanarak rasgele sayı motoru oluşturuyoruz.

bir seed_seq muhtelif rasgele sayı motorları başlatmak için kullanılabilir; seed_seq, her kullanıldığı zaman aynı tohum verilerini üretecektir.

Not: Tüm uygulamalar bir deterministik olmayan veri kaynağı sağlamaz. Uygulamanızın belgelerini std::random_device için kontrol edin.


Platformunuz sonra bazı diğer kaynaklar tohumlama için kullanılabilecek random_device olmayan bir deterministik sağlamazsa. std::chrono::high_resolution_clock

  • hafıza konfigürasyonu (time() tipik olarak çok düşük, genel olarak bir saniye bir çözünürlüğe sahip) gibi

    • yüksek çözünürlüklü bir saat adresine bağlı olarak değişir; Modern işletim sisteminde: madde Simple Portable C++ Seed Entropy alternatif kaynaklar bir dizi önerir uzay yerleşimi rasgele (ASLR)
    • CPU sayaçları veya rasgele sayı üreteçleri. C++ bunlara standart erişim sağlamaz, dolayısıyla onları kullanmayacağım.(Bir kereden fazla tohum eğer sadece konularda)
    • iplik kimliği
    • Basit sayaç Örneğin

    :

    #include <chrono> 
    #include <iostream> 
    #include <random> 
    #include <thread> 
    #include <utility> 
    
    using namespace std; 
    
    // we only use the address of this function 
    static void seed_function() {} 
    
    int main() { 
        // Variables used in seeding 
        static long long seed_counter = 0; 
        int var; 
        void *x = std::malloc(sizeof(int)); 
        free(x); 
    
        std::seed_seq seed{ 
         // Time 
         static_cast<long long>(std::chrono::high_resolution_clock::now() 
                .time_since_epoch() 
                .count()), 
         // ASLR 
         static_cast<long long>(reinterpret_cast<intptr_t>(&seed_counter)), 
         static_cast<long long>(reinterpret_cast<intptr_t>(&var)), 
         static_cast<long long>(reinterpret_cast<intptr_t>(x)), 
         static_cast<long long>(reinterpret_cast<intptr_t>(&seed_function)), 
         static_cast<long long>(reinterpret_cast<intptr_t>(&_Exit)), 
         // Thread id 
         static_cast<long long>(
          std::hash<std::thread::id>()(std::this_thread::get_id())), 
         // counter 
         ++seed_counter}; 
    
        std::mt19937 eng(seed); 
    
        uniform_real_distribution<double> urd(0, 1); 
    
        cout << "Uniform [0, 1): " << urd(eng); 
    } 
    
  • +0

    ile oynamak daha biraz açabilir misin? :) –

    +0

    bames53: Ben derlenmiş ve kodunuzu koştu. Belirleyici bir çıktı elde etmeye devam ediyorum, yani her defasında aynı. Platformumun bir sorunu olabilir. Windows 7 ve TDM-GCC derleyicisini çalıştırıyorum. – Argent

    +1

    konu Windows üzerinde bu libstdC++ geri deterministik uygulanmasına düşer olduğunu. Onlar henüz kararsızlıktan ötürü Windows işletim sistemlerine girmeyi denemediler (ve tabii ki Windows, libstdC++'nin * nix platformlarında kullandığı olanakları sağlamaz). Eğer programı VS2015 ile veya Linux'ta gcc ile oluşturursanız, tekrarlanan sonuçlar elde edersiniz. Eğer Windows'ta gcc kullanmaya devam etmek istiyorsanız, o zaman Windows CryptoAPI kullanarak bir şeyle 'random_device' değiştirmelisiniz. – bames53