unerwartetes Verhalten bei srand, bzw rand



  • Hi liebes C, bzw C++ Forum 🙂

    Ich bin gerade dabei eine kleine Funktion zu schreiben, die m Zufallszahlen zwischen 1 und 32 erzeugen soll, und sie in ein Array schreiben soll.
    Keine Zahl soll dabei doppelt reingeschrieben werden.

    Dafür wollte ich natürlich srand() bzw rand() benutzen.
    Leider passiert bei mir was ziemlich seltsames und ich kapiere einfach nicht, wieso meine Funktion so seltsam reagiert 😕 😡

    Hier ist der entsprechende Teil:

    ...
    ...
    
    int* choose_bits(int m)
    {
    	int bits[MAX_BITS];//MAX_BITS = 10
    
    	 int random;
    	 int* p;
    	 p = &random;
    
    	while (m != 0)
    	{
                    //Zufallszahl erzeugen
    		time_t t;
    		time(&t);
    		srand((unsigned int)t);
    		random = rand() % (ANZ_BITS + 1);
    
                    //prüfe, ob Zahl schon im Array steht, bzw 0 ist
    		if ((random != 0) && (bsearch(p, bits, MAX_BITS, sizeof(int), cmpfunc) == NULL))
    		{
    			bits[--m] = random;
    
    		}
    
    		else;
    
    	}
    
    	...
    

    Mir ist klar, dass die Zufallsfolgen, die hier erzeugt werden, Schwachsinn sind, da der Rechner sich zwar bei jedem Schleifendurchlauf die Zeit neu holt, er aber so schnell ist, dass er sich ganz oft hintereinander die gleiche Zeit holt.
    Dadurch werden dann also ganz oft hintereinander identische Zufallsfolgen geseeded und rand() liefert dann ganz oft hintereinander die gleiche Zahl.

    ABER:
    Trotzdem müsste doch meine if-Verzweigung richtig erkennen, dass eine Zahl schon im Array drin steht??
    Jetzt passiert es mir aber, dass er manche(!) Zahlen mehrmals reinschreibt; aber nicht beliebig oft, sondern scheinbar nach einem Muster??
    Bsp: er schreibt 4-Mal die 14 rein, und 2-mal die 10 (bei m = 6)

    Wieso schreibt er ausgerechnet 4, bzw 2-Mal diese beiden Zahlen rein?
    Ich sitze schon lange davor; kapiere dieses Verhalten aber einfach nicht ! 😮

    OK, also wenn ich nur 1x seede (vor der Schleife), dann funktioniert alles und er schreibt nichts doppelt hinein und alles ist perfekt 🙂

    Dieser Code hier funktionert also:

    int* choose_bits(int m)
    {
    	int bits[MAX_BITS]; // hier die Zahlen reinschreiben
    
    	int* bits_ptr;
    	bits_ptr = bits;
    
    	 int random;
    	 int* p;
    	 p = &random;
    	 //Diesmal vor der Schleife seeden
    	 time_t t;
    	 time(&t);
    	 srand((unsigned int)t);
    
    	while (m != 0)
    	{
    
    		random = rand() % (ANZ_BITS + 1);
    
    		//prüfe, ob Zahl schon im Array steht, bzw 0 ist
    		if ((random != 0) && (bsearch(p, bits, MAX_BITS, sizeof(int), cmpfunc) == NULL))
    		{
    			bits[--m] = random;
    
    		}
    
    		else;
    
    	}
    ...
    }
    

    Aber warum funktioniert dann nicht auch die erste Variante?
    Es ist zwar ineffizient und dumm; aber sollte doch trotzdem funktionieren?

    Ich will ja auch wissen, warum es jetzt funktioniert.
    Liegt es an bsearch() oder rand(), srand() ?

    Danke, falls dich das jemand bis zum Ende durchliest und eine Idee hat; ich wäre sehr dankbar 😉

    mfg
    Markus


  • Mod

    Guck dir mal eine Referenz zu bsearch genau an. Es gibt da eine Voraussetzung für die Benutzung von bsearch...



  • Richtig!
    Das Array muss sortiert sein! Das habe ich ganz vergessen..
    Danke 🙂



  • Wenn du jetzt auf die Idee kommst, das Array zu sortieren, direkt bevor du bsearch verwendest, machst du etwas falsch.



  • Das srand machst man nur einmal im ganzen Programm. Am Besten irgendwo am Anfang von main .

    Wenn ich mir die erste Zeile deiner Funktion anschaue, ahne ich Schlimmes:

    int* choose_bits(int m)
    {
        int bits[MAX_BITS]
    

    Ich hoffe deine letze Zeile (in der Funktion) sieht nicht so aus:

    return bits;
    

    Denn nach dem Befehl hört bits auf zu existieren.
    Du gibst also einen ungültigen Zeiger zurück.



  • Mach ein Array, in dem du die Zahlen von 1 bis 32 ablegst.

    Dann holst du dir eine Zufallszahl im Bereich von 0 bis 31 und nimmst ...
    ... diese als Index auf das Array. Die dort abgelegte Zahl ist dein gesuchter Wert.

    Jetzt schreibst du die letzte Zahl aus dem Array an diese Stelle.
    Dein Array ist jetzt kleiner, darum ist deine nächste Zufallszahl im Bereich von 0 bis 30 und nimmst ...


  • Mod

    Hat noch jemand anderes die Ahnung, dass hinterher diese Zahlen benutzt werden, um einzelne Bits in einem Integer zu setzen? Falls das so ist, drängt es sich doch auf, gleich einen passenden Integer mit m zufälligen gesetzten Bits zu erzeugen, anstatt eine Rube-Goldberg-Maschine dafür zu bauen.



  • DirkB schrieb:

    Das srand machst man nur einmal im ganzen Programm. Am Besten irgendwo am Anfang von main .

    Wenn ich mir die erste Zeile deiner Funktion anschaue, ahne ich Schlimmes:

    int* choose_bits(int m)
    {
        int bits[MAX_BITS]
    

    Ich hoffe deine letze Zeile (in der Funktion) sieht nicht so aus:

    return bits;
    

    Denn nach dem Befehl hört bits auf zu existieren.
    Du gibst also einen ungültigen Zeiger zurück.

    Nein, keine Angst; ich habe noch einen Pointer auf bits. Habe nur irrelevantes aus dem code weggelassen, damit er nicht noch länger wird. Es ging mir hier nur um das Verhalten von srand, bzw bsearch.

    SeppJ schrieb:

    Hat noch jemand anderes die Ahnung, dass hinterher diese Zahlen benutzt werden, um einzelne Bits in einem Integer zu setzen? Falls das so ist, drängt es sich doch auf, gleich einen passenden Integer mit m zufälligen gesetzten Bits zu erzeugen, anstatt eine Rube-Goldberg-Maschine dafür zu bauen.

    Ich will ein Programm zum "Verschlüsseln" eines Textes, bzw einer Datei schreiben.
    Dazu will ich dann jedes Byte, das in der Datei steht, erstmal "verlängern" auf 4 Byte(cast als int) und dann genau m Bits dieser Int Zahl invertieren.
    Ist natürlich kein Krypto-Algorithmus a la RSA, aber ich wollte sowas halt mal machen 😉

    Ich weiß jetzt nicht, wie genau du das mit dem "passenden Integer mit m zufälligen gesetzten Bits erzeugen" meinst.. Ich brauche halt m Zufallszahlen zwischen 1 und 32, um dann genau diese Bits jeder Zahl zu invertieren.

    mfg



  • Zum lernen der Sprache ist dein vorhaben ok. Doch wenn du hier von verschlüsseln sprichst wird mir schlecht.

    Mal abgesehen davon, wie stellst du dir die entschlüsselungs Funktion vor?



  • Ich habe "Verschlüsseln" doch extra in Klammern geschrieben 🙂
    Der Key zum Entschlüsseln enthält die Bit-Positionen, die vorher invertiert wurden.
    Die werden dann wieder zurückinvertiert.



  • blackroya schrieb:

    Der Key zum Entschlüsseln enthält die Bit-Positionen, die vorher invertiert wurden.
    Die werden dann wieder zurückinvertiert.

    Dann bekommst du den Key wenn ""verschlüsselt"" wurde? Oder wie ist das mit den Zufalls Zahlen?
    Das was du da machst ist völliger Bullshit.
    Versuche doch mal zbsp. Caesar oder eine monoalphabetische Substitution zu implementieren.



  • -lowbyte- schrieb:

    Das was du da machst ist völliger Bullshit.
    Versuche doch mal zbsp. Caesar oder eine monoalphabetische Substitution zu implementieren.

    Der Beitrag heißt übrigens nicht "Wie verschlüssele ich etwas so gut, dass tianhe-2 zwölf millionen Jahre brauchen würde, um es zu entschlüsseln"..


Log in to reply