RND

Aus C64-Wiki
Wechseln zu: Navigation, Suche
RND
Format: RND(<Zahl>)
Parameter
<Zahl>: bestimmt den Ausgangswert (Seed) für die Berechnung der Zufallszahl
Einordnung
Typ: numerische Funktion
Kontext: Arithmetik
Aufgabe: Erzeugen einer Pseudozufallszahl
Abkürzung: rN
Verwandte Befehle

Anmerkung: Dieser Artikel beschreibt die numerische BASIC-Funktion RND unter BASIC V2 des Commodore 64.


Die BASIC-Funktion RND() (Englisch: random[1]) dient zur Erzeugung von Zufallszahlen. Sie erzeugt eine pseudozufällige[2] Gleitpunktzahl im Bereich zwischen 0.0 (inklusive) und 1.0 (exklusive). Das Hilfsargument Zahl darf positiv, negativ oder Null sein:

  • < 0
    Bei einem negativen Wert wird dieser direkt für die Berechnung der Zufallszahl verwendet. Die Funktion RND() liefert für ein bestimmtes negatives Argument Zahl immer das gleiche Ergebnis zurück. Zum Beispiel ergibt RND(-42) immer 3.92374204e-08.
  • > 0
    Bei positivem Argument dient die jeweils letzte Zufallszahl als Ausgangswert für die Berechnung der nächsten Zufallszahl. Wenn man also die Funktion mit einem festen negativen Wert und danach immer mit positiven Werten aufruft, erhält man bei jedem dieser Programmläufe immer wieder die gleiche Zahlenfolge.
  • = 0
    Mit Null als Argument erzeugt der Commodore 64 die Zufallszahl direkt aus den Werten des Timers[3] und der Echtzeituhr[4] des CIA-Ein-/Ausgabe-Chips. Die Verteilung der Werte ist unter gewissen Umständen (z.B. schnelle aufeinander folgende Abfragen) nicht ganz so zufällig. Dieser Parameter sollte nur zur Initialisierung einer Zufallsreihe verwendet werden und entspricht etwa dem, was manche andere BASIC-Dialekte mit einer RAND- oder RANDOMIZE-Funktion abdecken.

In Programmen sieht man oft, dass am Programmanfang RND() mit der negativen Zeit aus der Variable TI und im weiteren Programmverlauf mit einer positiven Zahl, meistens 1, aufgerufen wird, um bei jedem Programmlauf eine andere Zahlenfolge zu erhalten.
Eine ähnliche Wirkung (mit anderen Werten) erzielt man auch durch den einmaligen Aufruf mittels RND(0), um die Zufallsfolge zu initialisieren und gefolgt von RND()-Aufrufen mit einem positiven Argument im weiteren Programmverlauf.

Leider hat Commodore bei der Implementierung des Zahlenfolge-Algorithmus einen Fehler eingebaut: Trotz eines 32-Bit-Seeds (also eines Wertebereichs von über 4 Milliarden verschiedener Zahlen) kann die Zufallszahlenfolge in Zyklen mit einer Länge von gerade einmal 723 Elementen hineinlaufen, so dass dann also nur noch 723 verschiedene Zahlen erzeugt werden und sich diese Sequenz ständig wiederholt.

Wird RND() nicht mit einem numerischen Argument aufgerufen, wird die BASIC-Fehlermeldung ?TYPE MISMATCH ERROR ausgegeben. Fehlt das numerische Argument oder sind zu viele Argumente gegeben, bricht der Interpreter mit ?SYNTAX ERROR ab.

[Bearbeiten] Beispiele

Siehe auch Beispielprogramme mit Zufallseffekten zum Thema Programmierung.

X=RND(-TI)             : REM Startwert setzen
PRINT INT(RND(1)*100)  : REM Wiedergabe von ganzen Zufallszahlen von 0 bis 99
PRINT INT(RND(1)*6)+1  : REM Wiedergabe von ganzen Zufallszahlen von 1 bis 6 (für Würfelsimulationen)
PRINT INT(RND(1)*49)+1 : REM Wiedergabe von ganzen Zufallszahlen von 1 bis 49 (für Lottosimulationen)
PRINT RND(0)*101+100   : REM Wiedergabe von zufälligen Gleitpunktzahlen von 100 bis 201 (exklusive)


Echtzeituhr für die Initialisierung verwenden:

POKE 56328,0    : REM Echtzeituhur 1/10s schreiben -> Uhr läuft ($DC08)
PRINT RND(0)    : REM Zufahlszahl abhängig von Timer und Echtzeituhr


Ein Beispiel, welches zeigt, warum RND(0), obwohl schneller als RND(1), keine gute Wahl ist:

  10 rem das programm zeigt den
  20 rem unterschied zwischen rnd(0)
  30 rem und rnd(1).
  40 rem es werden jeweils 1000 sterne
  50 rem zufaellig gesetzt und dann
  60 rem auf einen tastendruck gewartet.
  70 rem
  80 for i=0 to 1:print "{clr}";:poke 53280,7
  90 for j=1 to 1000:poke 1024+int(rnd(i)*1000),42:next
 100 print "{wht}rnd(";i;"{left} ){lt blue}":poke 53280,14:wait 198,1:get a$:next
 110 print "{clr}"

Bei RND(0) ist deutlich ein Muster zu erkennen, da die Funktion nur 256 verschiedene Werte liefert und damit nicht alle 1000 Zeichen auf dem Bildschirm erreicht werden können.

Basic RND 0.png Basic RND 1.png


Ein Beispiel[5], welches den Fehler in RND(>0) demonstriert, wenn mit einem "schlechten" Seed wie z.B. -7621 begonnen wird:

 1 print "{clr}";: x = rnd(-7621)
 2 for t = 1 to 100000: x = rnd(1): next: rem am Anfang ok, dann beginnt der Zyklus:
 3 x = int(rnd(1) * 40)
 4 y = int(rnd(1) * 25)
 5 poke 1024 + 40 * y + x, 160
 6 goto 3

Eigentlich müsste der Bildschirm immer mehr gefüllt werden, aber die für eine komplette Füllung nötigen 1000 verschiedenen Positionen werden nie erreicht.

[Bearbeiten] Quellen / Anmerkungen

  1. Englisch random; http://dict.leo.org/?search=random
  2. Siehe Wikipedia: Pseudozufallszahl
  3. CIA 1 Timer A für den KERNAL-IRQ-Takt.
  4. Echzeituhr ist nach Systemstart nicht aktiv, liefert also ohne Aktivierung keinen Beitrag.
  5. Die Fehler des Basic V2: RND()-Unzulänglichkeiten (Forum64)

[Bearbeiten] Weblinks

WP-W11.png Wikipedia: Pseudozufallszahl


In anderen Sprachen