Lottozahlen mach ich was falsch?



  • SeppJ schrieb:

    Und zwar 0.000002% häufiger. Absolut unbrauchbar.

    Klar ist natürlich nicht besonders viel. Mit rand() unter Windows wo RAND_MAX=32767 ist sieht das schon wieder schlechter aus. Jedenfalls ist meine Lösung nicht wesentlich komplizierter als die von heavylotto. Außerdem sehe ich irgendwie keinen Sinn darin absichtlich einen schlechteren Zufallszahlengenerator zu nehmen, wenn man schon die neuen C++11 Teile nutzt. Ob ich minstd_rand oder mt19937 schreibt macht nicht so den Unterschied.

    Wers noch nicht kennt: Ein Vortrag warum man besser nicht rand() benutzt und was man stattdessen besser nimmt: https://channel9.msdn.com/Events/GoingNative/2013/rand-Considered-Harmful


  • Mod

    Die Wahl des Zufallsgenerators und die Berechnung der richtigen Verteilung sind zwei getrennte Probleme.

    rand ist gut genug für Spielereien, wie hier. rand ist nicht gut genug für einige professionelle Anwendungen, wie beispielsweise wissenschaftliches Rechnen. Da es nicht wirklich einen Unterschied macht, ob man nun rand oder mt19937 schreibt, kann und sollte man auch für Spielereien etwas besseres als rand benutzen.

    Eine "Gleichverteilung" mittels modulo ist gut genug für Spielereien. Eine modulo-Verteilung ist sogar gut genug für sehr viele professionelle Anwendungen, mir fallt spontan kein Gegenbeispiel ein, außer man hat wirklich eine Verteilung, die sich über einen signifikanten Bereich des Zufallszahlenraums erstreckt. Die Verteilungsfunktionen sind komplizierter in der Benutzung (und theoretisch etwas langsamer) als ein einfaches Modulo. Die Modulo-Verteilung würde ich daher nicht so negativ darstellen.



  • Ich benutze immer noch gerne mein altes völlig transparentes System:

    class Random_spezial // siehe: http://www.math.keio.ac.jp/home2/matumoto/public_html/mt19937int.c 
    {
    private:
    	unsigned seed_;
    	const int N;
    	const int M;
    	const unsigned MATRIX_A;
    	const unsigned UPPER_MASK;
    	const unsigned LOWER_MASK;
    	const unsigned TEMPERING_MASK_B;
    	const unsigned TEMPERING_MASK_C;
    	unsigned TEMPERING_SHIFT_U(unsigned y) { return (y >> 11); }
    	unsigned TEMPERING_SHIFT_S(unsigned y) { return (y << 7); }
    	unsigned TEMPERING_SHIFT_T(unsigned y) { return (y << 15); }
    	unsigned TEMPERING_SHIFT_L(unsigned y) { return (y >> 18); }
    	static unsigned mt[624];
    	static int mti;
    
    public:
    	Random_spezial() :N(624), M(397), MATRIX_A(0x9908b0df),
    		UPPER_MASK(0x80000000), LOWER_MASK(0x7fffffff),
    		TEMPERING_MASK_B(0x9d2c5680), TEMPERING_MASK_C(0xefc60000),
    		seed_(static_cast<unsigned>(time(0)))
    	{
    		static bool seed_flag = 0;
    		if (!seed_flag)
    		{
    			sgenrand(seed_);
    			seed_flag = true;
    		}
    	}
    
    	void sgenrand(unsigned seed_)
    	{
    		mt[0] = seed_ & 0xffffffff;
    		for (mti = 1; mti<N; mti++) mt[mti] = (69069 * mt[mti - 1]) & 0xffffffff;
    	}
    
    	unsigned getNum() { return genrand() % (RAND_MAX + 1); }
    
    	unsigned genrand()
    	{
    		unsigned y;
    		static unsigned mag01[2] = { 0x0, MATRIX_A };
    
    		if (mti >= N)
    		{
    			int kk;
    			//if (mti == N+1) sgenrand(seed_); 
    			for (kk = 0;kk<N - M;kk++)
    			{
    				y = (mt[kk] & UPPER_MASK) | (mt[kk + 1] & LOWER_MASK);
    				mt[kk] = mt[kk + M] ^ (y >> 1) ^ mag01[y & 0x1];
    			}
    			for (;kk<N - 1;kk++)
    			{
    				y = (mt[kk] & UPPER_MASK) | (mt[kk + 1] & LOWER_MASK);
    				mt[kk] = mt[kk + (M - N)] ^ (y >> 1) ^ mag01[y & 0x1];
    			}
    			y = (mt[N - 1] & UPPER_MASK) | (mt[0] & LOWER_MASK);
    			mt[N - 1] = mt[M - 1] ^ (y >> 1) ^ mag01[y & 0x1];
    
    			mti = 0;
    		}
    		y = mt[mti++];
    		y ^= TEMPERING_SHIFT_U(y);
    		y ^= TEMPERING_SHIFT_S(y) & TEMPERING_MASK_B;
    		y ^= TEMPERING_SHIFT_T(y) & TEMPERING_MASK_C;
    		y ^= TEMPERING_SHIFT_L(y);
    		return y;
    	}
    };
    
    unsigned Random_spezial::mt[624];
    int Random_spezial::mti = 625;
    
    template<typename T_Generator> class Wuerfel
    {
    private:
    	const int maxzahl_;
    	const int maxrandom_;
    	T_Generator zahlengenerator_; // Template-Typ 
    
    public:
    	Wuerfel(int maxzahl) :maxzahl_(maxzahl), maxrandom_(RAND_MAX - (RAND_MAX%maxzahl)) {}
    
    	int wuerfelt()
    	{
    		int r;
    		do { r = zahlengenerator_.getNum(); } while (r >= maxrandom_);
    		return (r % maxzahl_ + 1);
    	}
    };
    
    int n = ...; // your choice  
    Wuerfel<Random_spezial> w(n);
    

    Im Code:

    Car myCar(w.wuerfelt() - 1, w.wuerfelt() - 1);
    

    Der Link ist übrigens inzwischen tot. 🙂



  • Erhard Henkes schrieb:

    Ich benutze immer noch gerne mein altes völlig transparentes System:

    Wozu? Es sieht völlig kaputt aus, da es von RAND_MAX abhängt. Abgesehen davon gibt keinen Grund, es zu verwenden, wenn wir seit C++11 eine bessere Alternative haben.


Anmelden zum Antworten