Zufallszahlen



  • Moin Leute,
    ich lerne weiter C++ (mithilfe vom Breymann) und bin mal wieder auf ein Problem gestoßen. In einem Beispiel generiert er Zufallszahlen mithilfe von random_device. Wenn ich das Programm mehrfach bei mir ausführe, bekomme ich immer die gleiche Zahl raus. Aber soweit ich das verstehe, sollte ja bei jedem Aufruf eine andere Zahl generiert werden. Verstehe ich den Code falsch oder mache ich irgendwas falsch?

    #include <iostream>
    #include <random>
    using namespace std;
    
    int main() {
      random_device rd;
      mt19937 generator(rd());
      int Zahl = generator(); 
      cout << "Loesung=" << Zahl << endl;
    }
    

    Zur Info: Ich arbeite unter Windows 10 und nutze den GNU g++ Compiler.



  • @Deuterium42

    Windows 10 und nutze den GNU g++ Compiler.

    Das ist das Problem. Wechsel Compiler oder Betriebssystem..



  • @manni66 sagte in Zufallszahlen:

    Das ist das Problem.

    so ein quatsch.



  • @Swordfish sagte in Zufallszahlen:

    so ein quatsch.

    weil? Siehe auch https://sourceforge.net/p/mingw-w64/bugs/338/

    Nimm Visual Studio oder nimm den g++ auf einem Nicht-Windows OS. Oder nimm random_device aus Boost, das geht auch unter Windows.


  • Gesperrt

    Oder du kannst es mit RdRand versuchen.

    #include <immintrin.h>
    
    class rdrand32
    {
    public:
    	static unsigned int min()
    	{
    		return 0;
    	}
    	static unsigned int max()
    	{
    		return static_cast<unsigned int>(-1);
    	}
    	unsigned int operator()() const
    	{
    		unsigned int random;
    		_rdrand32_step(&random); // use -mrdrnd compiler option for g++ / GCC C++ compiler
    		return random;
    	}
    };
    

    Mit -mrdrnd als Compiler-Option.

    int main() {
      rdrand32 rd;
      mt19937 generator(rd());
      int Zahl = generator(); 
      cout << "Loesung=" << Zahl << endl;
    }
    


  • Wieder so ein Beispiel, das die C++ Varianten des Random Generators auch noch genügned Fallstricke bergen.



  • Zu raten auf einen komplett anderen Compiler oder Betriebssystem umzusteigen ist absolut nicht zielführend und hilft überhaupt nicht das Problem zu beheben.

    Schnell darauf hinzuweisen, dass std::random_device in der Konstellation nicht funktioniert/implementiert ist und eine Alternative anbieten würde sehr viel mehr helfen.
    Ist zwar dann passiert, aber das musste gesagt werden.



  • @5cript sagte in Zufallszahlen:

    Zu raten auf einen komplett anderen Compiler oder Betriebssystem umzusteigen ist absolut nicht zielführend und hilft überhaupt nicht das Problem zu beheben.

    Doch, das ist zielführend. Wenn ich nach einem Buch aktuelles C++ lernen will, ist so ein Krüppelcompiler wie g++ auf Windows unbrauchbar. Irgendwelche Umgehungslösungen helfen da auch nicht weiter.



  • Ein workaround wäre Seed from std::chrono (siehe Example)

    Ist aber wie gesagt keine Lösung, denn das macht nicht das Selbe wie z. B. /dev/urandom:

    The random number generator gathers environmental noise from device drivers and other sources into an entropy pool. The generator also keeps an estimate of the number of bits of noise in the entropy pool. From this entropy pool random numbers are created.

    Sollte aber egal sein, denn sonst gibt es sowieso spezielle Crypto Bibliotheken.

    In der WinAPI gibt es evtl. auch Alternativen dazu, aber das müsstest Du selbst implementieren, wenn Du bei MinGW bleiben möchtest.

    Allgemein würde ich auch empfehlen unter Linux zu programmieren, ist einfach angenehmer (auch was Bibliotheken herunterladen und verwenden etc. angeht), und es schadet nicht mit Linux halbwegs umgehen zu können.

    Edit: Mein Ansatz für windows wäre (mit Vorsicht genießen, ich hab vielleicht noch Fehler drin, das passiert bei Crypto ganz schnell):

    #pragma once
    
    #include <string>
    #include <windows.h>
    #include <bcrypt.h>
    #include <ntstatus.h>
    
    class random_device {
    public:
    	using result_type = unsigned int;
    	
    	random_device(const std::string& token = "") {
    	}
    	
            random_device(const random_device&) = delete;
    	random_device& operator=(const random_device&) = delete;
    	
    	// user mode
    	result_type operator()() {		
    		result_type result{};
    		auto status = BCryptGenRandom(NULL, reinterpret_cast<PUCHAR>(&result), sizeof(result), BCRYPT_USE_SYSTEM_PREFERRED_RNG);
    		if (status != STATUS_SUCCESS) {
    			// error
    			return {};
    		}
    		return result;
    	}
    	
    	double entropy() const noexcept {
    		// value between 0 and std::numeric_limits<result_type>::digits
    		return 0.0; // ???
    	}
    	
    	static constexpr result_type min() {
    		return std::numeric_limits<result_type>::min();
    	}
    	
    	static constexpr result_type max() {
    		return std::numeric_limits<result_type>::max();
    	}
    };
    

    Man muss mit bcrypt.lib linken.



  • Das ist kein "Krüppelcompiler", das ist korrektes Verhalten laut Standard.



  • @TGGC sagte in Zufallszahlen:

    Das ist kein "Krüppelcompiler", das ist korrektes Verhalten laut Standard.

    Jaja



  • @manni66 sagte in Zufallszahlen:

    @5cript sagte in Zufallszahlen:

    Zu raten auf einen komplett anderen Compiler oder Betriebssystem umzusteigen ist absolut nicht zielführend und hilft überhaupt nicht das Problem zu beheben.

    Doch, das ist zielführend. Wenn ich nach einem Buch aktuelles C++ lernen will, ist so ein Krüppelcompiler wie g++ auf Windows unbrauchbar. Irgendwelche Umgehungslösungen helfen da auch nicht weiter.

    Ich kann dich jetzt nicht mehr ansatzweise Ernst nehmen.



  • @manni66 Halt lieber die Füschen still, du laberst quatsch.



  • @manni66 Du verwechselst hier eh nicht gerade die libstdc++ und GCC...?