Eine zufällige Zahl zwischen zwei Werten mit rand()



  • Ich möchte mit Hilfe von rand() eine Zahl zwischen zwei Werten HighValue und LowValue haben.

    Die Klasse:

    class RndColor
    {
    private:
    	int Color;
    	int HValue;
    	int LValue;
    
    public:
    	RndColor(void);
    	int RandomColor(int HighValue,int LowValue);
    };
    

    Die Methoden:

    RndColor::RndColor(void)
    {
    	int Color = 0;
    	int HValue = 0;
    	int LValue = 0;
    }
    int RndColor::RandomColor(int HighValue,int LowValue)
    {
    	srand(timeGetTime());
    	HValue = HighValue;
    	LValue = LowValue;
    	Color = (int)(rand()%HValue);
    	while(Color << LValue)
    	{
    		Color = (int)(rand()%HValue);
    	}
    	return Color;
    }
    

    Wenn ich jetzt zum Beispiel sage

    BColor.RandomColor(255,200)
    

    dann will ich dass diese Methode eine Zahl zwischen 200 und 255 zurückgibt.
    Komischerweise gibt er aber immer 0 zurück! Oo
    Weiß jemand,was ich da falsch gemacht habe?



  • while(Color << LValue)
    

    Nur ein '<'

    Edit: Übrigens kannst du die Schleife relativ leicht vermeiden.

    Color = ((int)(rand() % (HValue - LValue))) + LValue;
    

    mfg Kenrik



  • int RndColor::RandomColor(int HighValue,int LowValue) 
    { 
        srand(timeGetTime()); 
        return (int)(rand()%(HighValue-LowValue)+1)+LowValue; 
    }
    

    Probier mal dies, ist noch nicht getestet.
    🙂



  • Genau da lag der Fehler.

    Ich danke dir jetzt klappts auf einmal.

    Dieser billige fehler den Bitoperator mit dem Vergleichoperator zu verwechseln passiert mir immer wieder. ^^

    Ich scheine dadurch eine Endlosschleife gemacht zu haben und dadurch kam es nie zum return oder warum gab die Funktion immer den Wert 0 zurück?



  • Tobi3000 schrieb:

    Ich scheine dadurch eine Endlosschleife gemacht zu haben und dadurch kam es nie zum return oder warum gab die Funktion immer den Wert 0 zurück?

    Naja, es war keine komplette Endlosschleife, sonst wärst du gar nicht mehr rausgekommen. Aber die Endebedingung deiner Schleife ist "Color==0" - das dürfte den Rückgabewert erklären.

    btw solltest du den srand() Aufruf lieber in den Konstruktor verlagern.



  • Was ist denn übrigens timeGetTime() in srand? Das ist aber keine Standardfunktion. Oder hast Du die selbst definiert?

    Was das srand betrifft: Noch besser, als es in den Konstruktor zu schreiben, wäre übrigens, es nur einmal im gesamten Programm zu benutzen. Also entweder einmal am Anfang in der main oder eine andere Idee:

    class RndColor
    {
    private:
        int Color;
        int HValue;
        int LValue;
    
        static bool srandIsSet;
    
    public:
        RndColor(void);
        int RandomColor(int HighValue,int LowValue);
    };
    
    bool RndColor::srandIsSet=false;
    
    RndColor::RndColor ():
        Color (0), HValue (0), LValue (0)
    {
        if (!srandIsSet)
        {
            srand ((unsigned) time (NULL));
          /*Oder nach C++-Manier:
            srand (static_cast<unsigned> (time (NULL)));*/
    
            srandIsSet=true;
        }
    }
    


  • int RndColor::RandomColor(int HighValue,int LowValue)
    {
       srand(timeGetTime());
       return (int)(rand()%(HighValue-LowValue)+1)+LowValue;
    }
    

    warum +1 hier? dh wenn ich für highvalue: 20 und für LowValue: 10 übergebe...habe ich ja (rand()%11)+10...
    ist da srand(timeGetTime()); ...reicht ein srand(NULL); am anfang nicht?



  • steht im Übrigen in der FAQ der C-Runtime.



  • wie wär's mit:

    #include <limits>
    #include <ctime>
    #include <cstdlib>
    
    template< typename T >
    class random {
    
        private:
    
            T min;
            T max;
    
        public:
    
            random( ) : min( numeric_limits< T >::min( ) ), max( numeric_limits< T >::max( ) )
            {
                srand( time( 0 ) );
            }
    
            random( T pmin, T pmax ) : min( pmin ), max( pmax )
            {
            }
    
            ~random( ) { };
    
            T get( )
            {
    
             /* In Numerical Recipes in C: The Art of Scientific Computing
                (William  H.  Press, Brian P. Flannery, Saul A. Teukolsky,
                William T.  Vetterling;  New  York:  Cambridge  University
                Press,  1990 (1st ed, p. 207)), the following comments are
                made:
    
                  "If you want to generate a random integer between 1 and
                   10, you should always do it by
    
    	       j = 1 + (int)( 10.0 * rand( ) / ( RAND_MAX + 1 . 0 ) );
    
    	       and never by anything resembling
    
                   j = 1 + ( (int) ( 1000000.0 * rand( ) ) % 10 );
    
                   which uses lower-order bits."
             */
    
                return static_cast< T >( min + ( ( max + 1.0 ) * rand( ) / RAND_MAX ) );
            }
    };
    

    Greetz, Swordfish



  • warum die 1?



  • http://gamedev.dword.org/index.php?t=rants&a=show&i=39 😃

    NES-Spieler schrieb:

    bool RndColor::srandIsSet=false;
    
    RndColor::RndColor ():
        Color (0), HValue (0), LValue (0)
    {
        if (!srandIsSet)
        {
            srand ((unsigned) time (NULL));
          /*Oder nach C++-Manier:
            srand (static_cast<unsigned> (time (NULL)));*/
    
            srandIsSet=true;
        }
    }
    

    Wie wär's mit

    struct rand_initialisatorenklasse //;)
    {
    	rand_initialisatorenklasse() { srand (static_cast<unsigned> (time (NULL))); }
    };
    
    RndColor::RndColor ():
        Color (0), HValue (0), LValue (0)
    {
    	static rand_initialisatorenklasse initialisiere_die_zufaellerei;
    }
    

    ? 🙂



  • igor1 schrieb:

    warum die 1?

    Als Modulo-Ergebnis kann 0 rauskommen, dies ist nach der Aufgabenstellung nicht erwünscht.
    rand()%10 nicht wie du schreibst 11 , die 1 wird später hinzuaddiert. 🙂



  • Wie wäre es mit boost::random, bevor ihr hier versucht was halbes selber zu backen.



  • #include <iostream>
    #include <iomanip>
    #include <conio.h>
    #include <cstdlib>
    #include <ctime>
    
    /******************************************************************/
    class Random_spezial
    {
    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;
    
    /******************************************************************/
    
    class RandomStdlib // verwendet rand()
    {
    private:
       const unsigned int seed_;
    public:
       RandomStdlib():seed_( static_cast<unsigned>(time(0)) ){}
    
       int getNum() const
       {
         static bool seed_flag=0;
         if(!seed_flag)
         {
           srand(seed_);
           seed_flag = true;
         }
         return rand();
       }
    };
    
    /******************************************************************/
    
    class RandomTestEqual // Test auf Gleichverteilung
    {
    private:
       int num_;
    public:
       RandomTestEqual() : num_(RAND_MAX - 1){};
       int getNum()
       {
          num_++;
          if (num_ >= RAND_MAX) num_ = 0;
          return num_;
       }
    };
    
    /******************************************************************/
    
    template<typename T_Generator> class Wuerfel
    {
    private:
      const unsigned int maxzahl_;
      const unsigned int maxrandom_;
      T_Generator zahlengenerator_; // Template-Typ
    
    public:
      Wuerfel(unsigned int maxzahl):maxzahl_(maxzahl),maxrandom_(RAND_MAX-(RAND_MAX%maxzahl)) {}
    
      unsigned int wuerfelt()
      {
        unsigned int r;
        do{ r = zahlengenerator_.getNum(); }
          while ( r >= maxrandom_ );
        return ( r % maxzahl_ +1 );
      }
    };
    
    /******************************************************************/
    
    int main()
    {
      const unsigned long long Serie     = 3;
      const unsigned long long Versuche  = 30000000;
      const unsigned int limit           = 200;
      const unsigned int moeglichkeiten  = 6;
    
      Wuerfel<RandomTestEqual>  w0a(moeglichkeiten);
      Wuerfel<RandomTestEqual>  w0b(2);
      Wuerfel<RandomStdlib>     w1a(moeglichkeiten);
      Wuerfel<RandomStdlib>     w1b(2);
      Wuerfel<Random_spezial>   w2a(moeglichkeiten);
      Wuerfel<Random_spezial>   w2b(2);
    
      unsigned long long H[moeglichkeiten+1];
    
      for(unsigned long long i=1; i<Serie+1; ++i)
      {
        for(unsigned int j=0; j<moeglichkeiten+1; ++j) H[j] = 0;
    
        for(unsigned long long k=1; k<Versuche+1; ++k)
        {
          unsigned int wurf = w2b.wuerfelt(); // hier wird gewürfelt
    
          if(Versuche<limit) std::cout << wurf << " ";
          ++H[wurf];
        }
    
        for(unsigned int c=1; c<moeglichkeiten+1; ++c)
        {
          std::cout << std::endl << c << ": " << H[c] << " " <<
    std::setprecision(7)
                    << 100 * static_cast<float>(H[c]) / Versuche << " %";
          H[0] += H[c];
        }
        std::cout << std::endl << "Wuerfe insgesamt: " << H[0] << std::endl <<
    std::endl;
      }
      _getch();
    }
    


  • Lolz schrieb:

    Wie wäre es mit boost::random, bevor ihr hier versucht was halbes selber zu backen.


Log in to reply