Zufallszahlen fuer Bitset, ist das so richtig?



  • Hallo,

    ich versuche Zufallszahlen fuer ein Bitset zu generieren. Am Anfang wird geprueft wieviele Bits per block erhalten sind. Spaeter moechte ich dann mit std::uniform_int_distribution<>d(0,std::pow(2.0f,bpb)-1); den Bereich festlegen aus dem die Zufallszahlen generiert werden sollen. Leider stuerzt das Program in der Zeile ab. Wenn ich die Zeile auskommentiere funktioniert es.
    Was mache ich falsch?

    std::random_device rd;
    boost::dynamic_bitset<> generate(int n)
    { 
       std::mt19937 gen(rd());
       const int bpb  = boost::dynamic_bitset<>::bits_per_block; 
       std::vector<boost::dynamic_bitset<>::block_type>arr;
       arr.resize(n%bpb ? n/bpb+1 : n/bpb); 
       //std::uniform_int_distribution<>d(0,std::pow(2.0f,bpb)-1); 
       // auto gen = std::bind(d, rng); 
       std::generate(arr.begin(), arr.end(), gen); 
       boost::dynamic_bitset<> ret(std::begin(arr), std::end(arr)); 
       return ret; 
    }
    


  • Edit: Nicht richtig geguckt.



  • Sorry, wenn ich es auskommentiere muss man Sachen umbennennen:

    boost::dynamic_bitset<> generate(int n)
    { 
       static std::random_device rd;
       std::mt19937 rng(rd());
       const int bpb  = boost::dynamic_bitset<>::bits_per_block; 
       std::vector<boost::dynamic_bitset<>::block_type>arr;
       arr.resize(n%bpb ? n/bpb+1 : n/bpb); 
       std::uniform_int_distribution<>d(0,std::pow(2.0f,bpb)-1); 
       auto gen = std::bind(d, rng); 
       std::generate(arr.begin(), arr.end(), gen); 
       boost::dynamic_bitset<> ret(std::begin(arr), std::end(arr)); 
       return ret; 
    }
    


  • Sorry, wenn ich es auskommentiere muss man Sachen umbennennen:

    boost::dynamic_bitset<> generate(int n)
    { 
       static std::random_device rd;
       std::mt19937 rng(rd());
       const int bpb  = boost::dynamic_bitset<>::bits_per_block; 
       std::vector<boost::dynamic_bitset<>::block_type>arr;
       arr.resize(n%bpb ? n/bpb+1 : n/bpb); 
       std::uniform_int_distribution<>d(0,std::pow(2.0f,bpb)-1); 
       auto gen = std::bind(d, rng); 
       std::generate(arr.begin(), arr.end(), gen); 
       boost::dynamic_bitset<> ret(std::begin(arr), std::end(arr)); 
       return ret; 
    }
    


  • std::pow(2.0f,bpb)-1
    

    😮 ➡

    (1u << bpb) - 1
    

    Und anderes. Wieso ein vorzeichenbehaftete Typen?

    Aber verstehe ich dich richtig, du willst ein zufälliges Bitset mit N Bits erzeugen?
    Ich würde da pauschal einfach

    boost::dynamic_bitset<> generate(boost::dynamic_bitset<>::size_type N) // size_t statt int
    {
        boost::dynamic_bitset<> ret{N};
    
        static std::independent_bits_engine<std::minstd_rand, 1, uint32_t> engine(std::chrono::system_clock::now().time_since_epoch().count()); // Ich nehm mal nicht random_device, mein MinGW hat noch den Bug
    
        for( boost::dynamic_bitset<>::size_type ct = 0; ct < ret.size(); ++ct )
            ret[ct] = engine();
    
        return ret;
    }
    

    Nehmen, was auch funktioniert, aber vielleicht brauchst du ja was spezielles.
    Edit: Hmm, eine bernoulli_distribution geht auch, ist auch schöner. Ich will jetzt nicht noch extra zwei Engines benutzen, aber sonst wäre das besser.



  • Solltest du nicht lieber uniform_int_distribution<block_type>(0,block_type(-1)) verwenden?
    Edit: Besser wär's noch, wenn man direkt sagen könnte, wieviele Bits man haben will. Scheint's ja auch zu geben, wenn ich mir Sone's code angucke.

    Das ist std::pow sieht zerbrechlich aus. 2.0f ist float, floats haben typischerweise eine 24-Bit-Mantisse aus. Was kommt bei pow(2.0f,32) raus? Float oder double? Wenn float und block_type ist > als std::uint32_t, dann hättest du hier ein Problem.

    Versuch mal die Standardbibliothek im Debug-Modus zu betreiben. Die Toolchain von Microsoft erlaubt das, die GCC auch. Stichwort "safe iterators". Ich seh' da spontan nicht, warum da etwas abstürzen sollte. Schmeiß den Debugger an, verwende sämlilche Debug-Modi und geh da Schritt für Schritt durch ...

    BTW: n%bpb ? n/bpb+1 : n/bpb kann man auch (n+bpb-1)/bpb schreiben.



  • Sone schrieb:

    std::pow(2.0f,bpb)-1
    

    😮 ➡

    (1u << bpb) - 1
    

    Und anderes. Wieso ein vorzeichenbehaftete Typen?

    Aber verstehe ich dich richtig, du willst ein zufälliges Bitset mit N Bits erzeugen?
    Ich würde da pauschal einfach

    boost::dynamic_bitset<> generate(boost::dynamic_bitset<>::size_type N) // size_t statt int
    {
        boost::dynamic_bitset<> ret{N};
    
        static std::independent_bits_engine<std::minstd_rand, 1, uint32_t> engine(std::chrono::system_clock::now().time_since_epoch().count()); // Ich nehm mal nicht random_device, mein MinGW hat noch den Bug
    
        for( boost::dynamic_bitset<>::size_type ct = 0; ct < ret.size(); ++ct )
            ret[ct] = engine();
    
        return ret;
    }
    

    Nehmen, was auch funktioniert, aber vielleicht brauchst du ja was spezielles.
    Edit: Hmm, eine bernoulli_distribution geht auch, ist auch schöner. Ich will jetzt nicht noch extra zwei Engines benutzen, aber sonst wäre das besser.

    Danke fuer den Hinweis. std::independent_bits_engine kannte ich noch nicht.
    Aber verstehe ich das richtig das die For-Schleife ueber alle Bits einzeln itertiert und fuer jedes Bit eine eigen Zufallszahl generiert?

    @krümelkacker
    Ich bekomme die Meldung: R6010 - abort() has benn called



  • PartisanBelgrad schrieb:

    Aber verstehe ich das richtig das die For-Schleife ueber alle Bits einzeln itertiert und fuer jedes Bit eine eigen Zufallszahl generiert?

    Es geht natürlich direkter:

    boost::dynamic_bitset<> generate(boost::dynamic_bitset<>::size_type N) // size_t statt int
    {
        typedef boost::dynamic_bitset<> bitset;
    
        bitset ret;
    
        static std::independent_bits_engine<std::minstd_rand, bitset::bits_per_block, bitset::block_width_type> engine{std::chrono::system_clock::now().time_since_epoch().count()};
    
        while( ret.size() < N )
            ret.append( engine() );
        ret.resize(N);
    
        return ret;
    }
    

    Aber da arbeite ich mit append und nicht mit einem Puffer wie du. 😉


Anmelden zum Antworten