C - Zufällige Binärzahl/Dualzahl erzeugen

OrbitXN

Grünschnabel
Hallo liebe Forenmitglieder,

ist es möglich in C eine zufällige Dualzahl zu erzeugen in vorgegebener größe, also zum Beispiel eine 12 Bit Dualzahl wie 001010010001?
Ich habe schon Google durchforstet, jedoch nichts hilfreiches dazu gefunden. Ich möchte nämlich ein Spiel programmieren, dass 3 Schwierigkeitsstufen hat. Für die 1. Schwierigkeitsstufe brauche ich eine 4 Bit, für die 2 Stufe eine 8 Bit und für die 3 Stufe eine 12 Bit binäre Zufallszahl.

Die einzige Möglichkeit die ich hier sehe wäre eine zufällige Dezimalzahl zu erzeugen und diese dann in eine Binärzahl umzuwandeln, jedoch bin ich mir nicht sicher ob das genau so geht wie ich mir das vorstelle, weil ich ja genau die größe/länge brauche, also wenn bei der 3. Stufe (12Bit) eine Zahl, z. B. "4" generiert wird, sollen davor noch 8 Nullen sein (0000 0000 0100), hoffe ihr versteht was ich mein.

Habe erst jetzt mit der C Programmierung angefangen, deswegen weiß ich nicht genau wie ich das realisieren kann.

Danke schon mal für eure Hilfe :)
 

Bratkartoffel

gebratene Kartoffel
Premium-User
Hi,

12 Bit, das entspricht einer Zahl im Bereich [0,4095].
Du kannst nun so vorgehen, dass du dir eine zufällige 16 Bit-Zahl erzeugst (z.B. mit rand()) und dann durch ein logisches AND mit einer Maske diese auf die gewünschte Länge "zuschneiden" kannst.

Beispiel
Code:
Zahl:  32673
Binär: 0111 1111 1010 0001

4 Bit: 2^5 - 1 = 15
Binär: 1111

Ausrechnen:
Zahl:     0111 1111 1010 0001
AND
Maske:    0000 0000 0000 1111
=
Ergebnis: 0000 0000 0001 (1)

Oder mit 8 Bit:
8 Bit = 2^9 - 1 = 255
Binär: 1111 1111

Ausrechnen:
Zahl:      0111 1111 1010 0001
AND
Maske:     0000 0000 1111 1111
=
Ergebnis:  0000 0000 1010 0001 (161)

Du kannst das alles natürlich auch auf "normaler" Dezimal-Ebene machen, du musst hier nichtsi nBinär umrechnen. Das habe ich hier nur händisch gemacht, so dass du das Prinzip einer Maske verstehst.

Grüsse,
BK
 
Zuletzt bearbeitet:

OrbitXN

Grünschnabel
Ja richtig das ist so gewollt das es den Zahlenbereich [0,4095] hat, bei 12 Bit.
Danke für die Erklärung. Hab das Beispiel denk ich auch verstanden. Jedoch versteh ich nicht so ganz wie mir das weiterhilft (nicht böse gemeint, vielleicht versteh ich es auch nicht), weil damit erzeuge ich dann eine zufällige 16 Bit-Zahl, diese schneide ich dann auf die gewünschte Länge wie zum Beispiel 4 Bit, dann erhalte ich eine 4 Bit Zahl. Das Problem dabei ist, so wie ich es dem Beispiel entnehme, habe ich zum Schluss immer eine Länge von 16 Bit auch wenn ich es zu einer 4 Bit Zahl zugeschnitten habe, also immer so viele Nullen davor (0000 0000 0000 0001). Ich brauche jedoch immer die richtige Länge, also wenn es eine 4 Bit Zahl ist (0001), wenn es eine 8 Bit zahl ist (0000 0001) und bei 12 Bit (0000 0000 0001). Oder hab ich das doch nicht genau verstanden und das funktioniert genau so, das mit den Masken?
 

Bratkartoffel

gebratene Kartoffel
Premium-User
Hi,

die Zahl ist im Speicher nun mal einfach 16 oder 32 Bit lang, je nachdem wie du sie definierst. 12 Bit gibt es nicht als Datentyp.
Wenn du das ganze dann als Binärzahl formatieren willst, dann darfst du halt von den 32 Bit von die letzten 12 Bit umwandeln.

Grüsse,
BK
 

cwriter

Erfahrenes Mitglied
Das Problem dabei ist, so wie ich es dem Beispiel entnehme, habe ich zum Schluss immer eine Länge von 16 Bit auch wenn ich es zu einer 4 Bit Zahl zugeschnitten habe, also immer so viele Nullen davor (0000 0000 0000 0001).
Um das vielleicht etwas anders anzuschauen:
Bei Zufallszahlen geht es um Komplexität. Eine Zahl ist genau dann zufällig, wenn jedes Bit mit 50% Wahrscheinlichkeit 0 und mit 50% Wahrscheinlichkeit 1 ist.
Somit kannst du Zufallszahlen kürzen, indem du sagst, dass gewisse Bits immer denselben Wert haben, denn dann sind sie ja nicht mehr zufällig. Jedes Bit, das du deterministisch setzt, reduziert den Zufallsgehalt um die Hälfte, da du ja 2 Möglichkeiten wegnimmst.

Die 0en ändern den Wert auch nicht; ist ja dasselbe wie im Dezimalsystem, wo 0003 == 3 gilt.
Gibt es einen Grund, warum du dich so auf die Länge konzentrierst? Willst du die einzelnen Bits lesen? Dann gibt es immer die Möglichkeit, nur die Bits zu lesen, die dich interessieren.
C:
srand(time(NULL));
int rd = rand();
for(int i = 0; i < 4; ++i) {
    printf("Bit an Stelle %d: %d\n", 4 - 1 - i, (rd >> i) & 1);
}
// >> shiftet den Wert um 1 Bit arithmetisch nach rechts (Division durch 2):
//0101 >> 1 == 0010
//0101 == 5, 5 / 2 == 2, 0010 == 2
Allerdings nennt man dies Bit-Banging aus gutem Grund: Es ist relativ ineffizient.

Vielleicht kannst du uns ja sagen, wozu du den Wert dann brauchst, damit wir uns etwas unter dem Einsatzzweck vorstellen können.

Gruss
cwriter
 

ComFreek

Mod | @comfreek
Moderator
Eine Zahl ist genau dann zufällig, wenn jedes Bit mit 50% Wahrscheinlichkeit 0 und mit 50% Wahrscheinlichkeit 1 ist.
Ich bin mir sicher, dass @cwriter das weiß, jedoch würde ich gerne im Sinne des Threaderstellers (pedantisch) anmerken, dass die obige Aussage nur gilt, wenn man von einer Gleichverteilung (auch uniforme Verteilung genannt) redet.
Wenn du eine (endliche) Menge von Ergebnissen (Zahlen 1-6 bei einem Würfel) hast, dann bedeutet Gleichverteilung, dass jedes Ergebnis mit derselben Wahrscheinlichkeit auftritt. Beim Würfel also z. B. mit 1/6.

Manchmal möchte man jedoch gewisse Ergebnisse wahrscheinlicher haben. Stell dir ein Karteikartensystem vor: Man möchte dem Schüler eine Karteikarte geben, wobei Karteikarten, die der Schüler schlecht bearbeitet hat, häufiger kommen sollen als neue. Trotzdem möchte man, dass das ganze ohne System, also "zufällig" geschieht.
Man kann also auch von Zufall reden, obwohl nicht jedes Ergebnis gleichwahrscheinlich ist.