Zufallszahlen

Wie erzeugt man eine Zufallszahl?

In Javascript gibt es die Funktion Math.random(), welche dazu da ist, einen Zufallswert zu liefern.
Schreiben Sie ein kleines Programm, welches die folgenden Zeilen enthält:
var Zufallszahl;
Zufallszahl = Math.random();
document.write (Zufallszahl);
Sie werden schnell feststellen, dass Sie bei jeder Ausführung des Programms eine andere Zufallszahl erhalten. Die Zufallszahl ist immer eine Kommazahl zwischen 0 (inklusive) und 1 (exklusiv), d.h. die Zahl kann exakt 0 sein, aber sie ist auf jeden Fall immer kleiner als 1.

Wie erhält man größere Zahlen als die generierten Werte?

Sie müssen nur den generierten Zufallswert mit einem selbst gewählten Faktor multiplizieren, z.B. ...
Zufallszahl = 10 * Zufallszahl;
Im obigen Fall erhalten Sie jetzt Zufallszahlen zwischen 0 (inklusive) und 10 (exklusive), d.h. die Zahl kann exakt 0 sein, ist aber auf jeden Fall immer kleiner als 10. Diese Zufallszahlen sind aber immer noch Kommazahlen.

Wie rundet man die Zufallszahlen auf ganze Zahlen?

Zum Runden der Kommazahlen auf ganze Zahlen gibt es in Javascript die Funktion Math.round().
Zufallszahl = Math.round( Zufallszahl );
Wenn wir jetzt den Wert der Variable Zufallszahl ausgeben, dann sehen wir ganze Werte. Leider ist die Häufigkeit unterschiedlich.

Gleiche Häufigkeit der Zufallszahlen

Das Problem

ZufallszahlWahrscheinlichkeit1.png

Die Lösung

Wenn man vor dem Runden 0,5 vom Zufallswert subtrahiert, dann ist die Wahrscheinlichkeit gleich verteilt für die Werte 0-9.
Zufallszahl = Zufallszahl - 0.5;
Dummerweise fehlt jetzt die 10 komplett!

Wir müssen also nach dem Generieren der Zufallszahl erst einmal die Skala vergrößern und erst anschließend die 0,5 abziehen. So bekommen wir das Problem mit dem folgenden Trick in den Griff:
Zufallszahl = 11 * Zufallszahl - 0.5;
Wir erhalten mit der obigen Transformation des Zufallswertes die folgende neue Skala. Nach dem Runden ergeben sich Werte mit gleicher Häufigkeit zwischen 0 und 10.
ZufallszahlWahrscheinlichkeit2.png

Geht das alles nicht einfacher?

Da wir einfach nur ein paar ganze Zahlen in einem vorgegebenen Bereich (z.B. 1-100) generieren möchten, können wir das tatsächlich auch einfacher erledigen. Eine mit der Funktion Math.random() erzeugte Zufallszahl wird mit der Anzahl der zu erzeugenden Zahlen multipliziert, z.B. 100 * Math.random().
Die ganzen Zahlen von 0 bis 99 stellen einen Wertebereich von 100 Zahlen dar. Die 100 selbst benötigen wir nicht. Das bedeutet, dass wir von den generierten Kommazahlen einfach nur alles nach dem Komma abschneiden müssen um diesen Wertebereich zu erhalten. Das macht man mit der Funktion Math.floor().
// Zahlen von 0-99
var anzahl=100;
var ganzeZahl = Math.floor( anzahl * Math.random() );
Wenn ich jetzt einen Zahlenbereich benötige, welcher mit 1 oder einem anderen Offset anfängt, so muss ich diesen Wert einfach nur addieren.
// Zahlen von 1-100
var anzahl = 100;
var offset = 1;
var ganzeZahl = Math.floor( anzahl * Math.random() ) + offset;

Lesen Sie mehr zu den Funktionen Math.floor() und Math.ceil(), z.B. unter folgenden Links:


Runden, siehe Math.round() bzw. Math.floor():

Für Fortgeschrittene:


Beispiele

Beispiel 1 - Klassisches Runden einer Zufallszahl, d.h. ab .5 wird aufgerundet und darunter abgerundet:
var zufall;
 
// Ein Wert zwischen 0 und 1 - gleichverteilt und mit gleichen Wahrscheinlichkeiten!
zufall = Math.random();
 
// Ein Wert zwischen 1 und inkl. 30
zufall = 0.5 + 30*zufall;
 
// Es soll eine ganze Zahl werden! Es wird gerundet.
zufall = Math.round(zufall);
 
// Wert ausgeben
document.write(zufall);
Beispiel 2 - Abschneiden der Ziffern nach dem Komma ist in der Programmierung oft einfacher verständlich, schneller zu programmieren und performanter in der Programmausführung:
    var feld;
    var smartphones = new Array( "samsung", "apple", "nokia" );
 
    // Math.random liefert einen Wert zwischen 0 und 1,
    // d.h. größter Wert ist 0,9999999999...
    // und das ist noch der falsche Wertebereich
    feld = Math.random();
    document.write( "Math.random hat folgenden Wert zufällig ermittelt: " + feld + "<br>")
 
    // Ein Wert zwischen 0 und der Länge des Arrays (exklusive)
    // aber leider immer noch nur eine Fließkommazahl,
    // welche wir als Feldindex nicht nutzen können!
    feld = feld * smartphones.length;
    document.write( "Nach Multiplikation mit der Länge des Arrays ist der neue Wert: " + feld + "<br>" )
 
    // Es soll eine ganze Zahl sein! Der Feldindex läuft nicht von 1-x,
    // sondern von 0-(x-1), d.h. abrunden ist angesagt.
    // Dafür gibt es die Funktion Math.floor
    feld = Math.floor(feld);
    document.write( "Nach Ausführen der Funktion ist der Feldindex: " + feld + "<br>")
 
    // Wert ausgeben
    document.write( "Smartphone = " + smartphones[feld] + "<br>" );
    document.write( "Wiederholung F5" );
Beispiel 3 - Testen der zufälligen Verteilung - Abfrage des Auftretens konkreter Werte:
     // Eine konkrete Abfrage auf genaue Zahlen ohne Rundung ist sinnlos!
     // Der folgende Test zeigt, dass JEDE erwartete Zahl (zufällige Auswahl)
     // trotz sehr vieler Versuche anscheinend nie generiert wird.
     // Die Schleifendurchläufe können auf leistungsfähigen Rechnern noch erhöht werden.
     // Die Ausbeute wird nicht besser.
 
     var zufallszahl=0;
     var counter = new Array(10);
     var tmp;
 
     // Vorbelegung der Zählerstände mit 0
     for( var i=0; i<counter.length; i++ )
     {
       counter[i]=0;
     }
 
     // x-mal innere Schleife wiederholen
     for( var j=0; j<1000; j++ )
     {
       for( var k=0; k<10000; k++ )
       {
         if( (zufallszahl=Math.random()) == 0 )
         {
           document.write("<h1>----------------------------------- 0 -----------------------------------</h1>");
         }
 
         if( zufallszahl == 0.23 )
         {
           document.write("<h1>----------------------------------- 0.23 -----------------------------------</h1>");
         }
 
         if( zufallszahl == 0.412 )
         {
           document.write("<h1>----------------------------------- 0.412 -----------------------------------</h1>");
         }
 
         if( zufallszahl == 0.5 )
         {
           document.write("<h1>----------------------------------- 0.5 -----------------------------------</h1>");
         }
 
         if( zufallszahl == 0.63 )
         {
           document.write("<h1>----------------------------------- 0.63 -----------------------------------</h1>");
         }
 
         if( zufallszahl == 0.721 )
         {
           document.write("<h1>----------------------------------- 0.721 -----------------------------------</h1>");
         }
 
         tmp=Math.floor( zufallszahl*counter.length );
         ++counter[tmp];
       }
       for( var l=0; l<counter.length; l++ )
       {
         document.write( (l+1) + ": " + counter[l] + ", " );
       }
       document.write( "<br>" );
     }
Beispiel 4 - Testen der zufälligen Verteilung:
     // Wie verteilen sich die zufällig ermittelten Zahlen zwischen 0 und <1
     // wenn man diese z.B. in 100 Abschnitte einteilt?
     // Das Ergebnis des folgenden Quelltextes sollte zeigen,
     // dass die Verteilung der Zufallszahlen einigermassen gleichmaessig erfolgt.
     var abschnittscounter = new Array(100);
 
     for( var i=0; i<abschnittscounter.length; i++ )
     {
       abschnittscounter[i]=0;
     }
 
     for( var j=0; j<1000; j++ )
     {
       for( var k=0; k<10000; k++ )
       {
         zufallszahl=Math.random();
         tmp=Math.floor( zufallszahl*abschnittscounter.length );
         ++abschnittscounter[tmp];
       }
       for( var l=0; l<abschnittscounter.length; l++ )
       {
         if( l%15 == 0 )
         {
           document.write("<br>");
         }
         document.write( (l+1) + ": " + abschnittscounter[l] + ", " );
       }
       document.write( "<br>" );
     }