Hallo Besucher, der Thread wurde 14k mal aufgerufen und enthält 63 Antworten

letzter Beitrag von goloMAK am

Der Befehl "RND"

  • Hallo zusammen,


    Mir ist soeben aufgefallen, das der RND Befehl ja nicht wirklich "Zufaellig" ist. Nachjedem Systemneustart kommt IMMER die Selbe Zahl raus, zum Beispiel bei "A=INT(16*RND(1))+1" kommt bei mir IMMER 3 raus und dannach IMMER 1 usw. . Meine Frage, ist es überhaupt möglich eine "richtige" Zufallszahl mit einem Computer zu generieren, also egal ob PC oder C64 und egal ob Assembler oder Basic oder C++.


    MfG
    Soldier

  • Wie aus dem Artikel ersichtlich wird nur bei RND(0) "Pseudo-Zufällige" Zahlen aus der Systemuhr errechnet, bei RND(1) kommt halt immer dieselbe Zahlenfolge.


    Bei RND(0) müsste man auch immer genau zur selben Zeit nach Reset (oder stromunterbrechung ?) die Funktion aufrufen um dieselbe Zhal zu erhalten.


    Um noch "bessere" Zufallszahlen zu erstellen, kann man "Rauscheingänge" benutzen, also die Pseudo-Zufallszahl mit einen Wert multiplizieren der auf einen "unsauberen" Signal beruht.
    (müsste auch am c-64 gehen, allerdings weiß ich jetzt da keinen Befehl für *g*)

    Am PC geht das noch einfachen, weil da ja eine fortlaufende Systemzeit (beim C-64 ist ohne Strom die Uhr gelöscht, soweit ich weiß) existiert, die als unabhängig vom Reset/externen Stromversorgung ist. Daher sollte jede "neuere" Programiersprache da ohne Probleme "pseudo-zufallszahlen" liefern, die sich nicht wiederholen (Pseudo-zufall deshalb, weil sie aus anderen Zahlen errechnet wird, aber für den Anwender nicht vorhersehbar...)


    sl FXXS

  • Zitat

    Original von Soldier
    Meine Frage, ist es überhaupt möglich eine "richtige" Zufallszahl mit einem Computer zu generieren, also egal ob PC oder C64 und egal ob Assembler oder Basic oder C++.


    Das ist eine fast philosophische Frage und die Geister streiten sich etwas darüber.
    Da ein Computer zur Ermittlung von Zufallszahlen immer einen SEED braucht, um die Zufallszahl zu "berechnen" wird es nie eine 'echte' Zufallszahl sein.
    Aber sie kann sehr zufällig sein :)

  • Hab ich doch oben schon gesagt...

    Zitat

    Original von FXXS
    Um noch "bessere" Zufallszahlen zu erstellen, kann man "Rauscheingänge" benutzen, also die Pseudo-Zufallszahl mit einen Wert multiplizieren der auf einen "unsauberen" Signal beruht.
    (müsste auch am c-64 gehen, allerdings weiß ich jetzt da keinen Befehl für *g*)

    kennt jemand dafür nen Basic befehl oder geht das nur in Assembler ?


    sl FXXS

  • So bekommst du beliebig viele Zufallszahlen über denn SID holen und ausgegeben:

    Code
    1. 10 POKE 54290,129
    2. 20 POKE 54287,100
    3. 30 PRINT PEEK(54299)
    4. 40 GOTO 30


    Leider kannst du aber die dritte Stimme des SID nicht mehr benutzen. Sollte aber oft auch nicht nötig sein.

  • Zitat

    Original von FXXS
    Wie aus dem Artikel ersichtlich wird nur bei RND(0) "Pseudo-Zufällige" Zahlen aus der Systemuhr errechnet, bei RND(1) kommt halt immer dieselbe Zahlenfolge.


    So allgemein ist das aber durchaus mißverständlich. Man könnte den Artikel durchaus ergänzen. Ich mache mal einen Vorschlag, was alles drinnen stehen könnte:


    Also mal etwas weiter ausgeholt: Eine Zufallszahlengenerator (besser: Pseudo-Zufallszahlengenerator, Pseudorandom number generator PRNG) ist ein Algotihmus, der eine unendliche Folge von Zahlen aus einem bestimmten Bereich erzeugt, die den (erwarteten) Eigenschaften von richtigen zufälligen Prozessen entsprechen. Die gängigen Verfahren hierzu basieren darauf, dass man von einer bestimmten Zahl (dem sogenannte "Seed") ausgeht. Auf diesem werden nun ein paar mathematische Operationen ausgeführt (z.B. Multiplikationen, Additionen, Herumschieben von Bits), woraufhin man eine neue Zahl erhält. Diese neue Zahl wird der Seed für den nächsten Aufruf von RND. Weiterhin wird diese neue Zahl entweder vollständig oder teilweise als neue Zufallszahl zurückgegeben.


    Aufgrund der Eigenschaften von Computern (insbesondere ihrem begrenzten Speicher) folgt unmittelbar, dass so eine Folge von Zufallszahlen zwar unendlich sein, allerdings nur einen endlichen Zyklus haben kann. D.h.: Nach einer gewissen Anzahl von Elementen wiederholen sich die Zufallszahlen wieder.


    Das oben beschrieben ist auch das Verhalten, wenn man RND mit einem positiven Argument, also z.B. RND(1), aufruft. Dummerweise ist der Seed beim C64 (und vielen anderen Rechnern) nach einem Neustart des Rechners immer der gleiche, so dass immer die gleiche Folge von Zufallszahlen herauskommt.


    Daher haben sich findige Leute folgendes überlegt: Man kann der RND-Funktion sagen, dass sie den Seed vergessen soll und stattdessen einen neuen nehmen soll. Dies macht sie, wenn sie ein negatives Argument bekommt, wobei das Argument dann eben der Seed ist. Aus diesem Grunde wird ein RND(-1) auch immer das gleiche Ergebnis zurückliefern, ebenso wie eine RND(-2) oder RND(-6E-30).


    Hat man nun eine zufällige Quelle (der Rauschgenerator vom SID wäre denkbar) und damit eine (nicht-negative) Zahl x erhalten, dann kann man den Zufallszahlengenerator mit RND(-x) auf einen neuen Anfangswert setzen. Darauffolgende Aufrufe der RND-Funktion sollten allerdings dann auch wieder ein positves Argument haben (RND(1)), weil sonst der Sinn der Zufallszahlenfunktion irgendwie konterkariert wird.


    Hat man nun keine zufällige Quelle zur Hand, eignet sich als Erzeuger für einen neuen Seed auch die Zeit seit dem Einschalten. Eine Variante hierfür ist RND(-TI), mit der man das erreicht. Eine andere ist RND(0), die etwas ganz ähnliches dazu macht.


    Wichtig ist auch hier: Nach dem Setzen des Seeds mit RND(0) sollten die weiteren Zufallszahlen wieder mit RND(1) erzeugt werden. Nur so arbeitet der Zufallszahlengenerator so, wie er es soll.


    Von Empfehlungen, RND(1) zu vermeiden und stattdessen nur RND(0) oder RND(-x) zu benutzen, ist also dringend abzuraten! (Es sei denn, der Zufallszahlengenerator im CBM-Basic ist {b]extrem[/b] schlecht. Hierzu müßte man das mal untersuchen, wozu ich aber keine Zeit und Lust habe.)


    Wenn jemand mehr über Pseudozufallszahlen und vor allem auch die vielen Fallstricke lesen möchte, kann ich nur die (etwas betagte) "Bibel" empfehlen: Donald E. Knuth, "The Art of Computer Programming. Vol. 2: Seminumerical Algorithms" (2. Auflage 1981). Wie gesagt, etwas betagt, aber mit einer sehr detaillierten Beschreibung.


    Gruß,
    - Spiro.

  • Zitat

    Original von strik
    o allgemein ist das aber durchaus mißverständlich. Man könnte den Artikel durchaus ergänzen. Ich mache mal einen Vorschlag, was alles drinnen stehen könnte:


    Hi Spiro, wenn du den Link in meinem letzten Posting verfolgt hättest, wärest du auf genau die Aussagen gestoßen, die du eben gemacht hast (nur kürzer). :roll:


    Arndt

  • Hallo Arndt,

    Zitat

    Original von GoDot
    Hi Spiro, wenn du den Link in meinem letzten Posting verfolgt hättest, wärest du auf genau die Aussagen gestoßen, die du eben gemacht hast (nur kürzer).


    Ich gebe zu, dem Link erst nach dem Schreiben gefolgt zu sein. Danach wollte ich mein Geschreibsel aber nicht mehr kürzen.


    Allerdings fehlen IMHO bei dir dann doch noch ein paar Informationen. Über den Zyklus schreibst du z.b. gar nichts. Du empfiehlst, RND(-TI) und dann RND(1) zu machen, ohne es wirklich zu begründen. Auch sagst du in einem Nebensatz, dass man RND(-TI) häufiger zur Initialisierung benutzen sollte/könnte - eine gefährliche Empfehlung, wenn man halbwegs brauchbare Zufallszahlen benötigt. Hier würde ich auf die Äußerungen von Don Knuth zum "Super-Zufallszahlengenerator" aus dem oben zitierten Buch verweisen wollen, wo erläutert wird, wieso das problematisch ist.


    Aber vielleicht hast du trotzdem recht: Wenn ich gute Zufallszahlen benötige würde ich RND() eh nicht benutzen. ;)


    Gruß,
    - Spiro.

  • Zitat

    Original von strik
    Auch sagst du in einem Nebensatz, dass man RND(-TI) häufiger zur Initialisierung benutzen sollte/könnte - eine gefährliche Empfehlung, wenn man halbwegs brauchbare Zufallszahlen benötigt.


    Oh, verstehe, da hab ich unklar gesprochen. Was ich meinte, war, dass man RND(-TI) ruhig bei jedem Neustart einer Session (in der die Zufallszahl benötigt wird, z.B. bei jedem Start eines Roulette-Tisches, wobei man in diesem gedachten Spiel auch was anderes als Roulette spielen können würde) benutzen kann. Auf jeden Fall aber nur einmal pro Einsatz-Zyklus (halt dem gedachten Roulette-Tisch, ich hab im C64-Wiki dazu gesagt "später im Programm nur RND(1)"). Danke für den Hinweis. Was ich auch weggelassen hatte, war deine Beschreibung der Bitverschiebungen, die das Basic V2 bei RND ganz so vornimmt, wie du gesagt hast. :)


    Arndt

  • In diesem Zusammenhang ist die immer gleiche Zufallszahlenreihenfolge bei einem bestimmen Initialwert ja auch ganz lustig.
    Keine Ahnung wo ich das mal vor Jahren gesehen habe, aber der ging es darum Anhand eines bestimmen Initialwerte sinnvolle Wörte aus einer "Zufallszahlen" Reihenfolge (mit den Werte von 1-26) zu bekommen. Es schreibt die Zahlen dann einfach als Buchstabe auf den Bildschirm:


    Also mit folgendem Programm:


    Code
    1. 10 INPUT"INITIALWERT",A
    2. 20 INPUT"LAENGE",B
    3. 30 C=RND(-A);
    4. 40 FOR D=1TOB
    5. 50 PRINT CHR$(RND(1)*26+65);
    6. 60 NEXT



    Gebt mal folgenden Werte für Initalwert und Länge ein: :prof:


    9022 und 5
    39644 und 6


    oder aber


    1726957 und 5


    :bgdev

  • Zitat

    Original von GoDot
    Auf jeden Fall aber nur einmal pro Einsatz-Zyklus (halt dem gedachten Roulette-Tisch, ich
    hab im C64-Wiki dazu gesagt "später im Programm nur RND(1)").


    Wobei hier die Frage ist, was ein Einsatz Zyklus ist. Bei einem Roulette-Tisch brauche ich ja jeweils nur eine einzige Zufallszahl. ;)


    Als Faustregel kann man vielleicht folgendes sagen:

    • RND(1) so häufig wie möglich einsetzen
    • RND(0) oder RND(-TI) beim Programmstart einsetzen.
    • RND(0) oder RND(-TI) sollte nur (sprich: höchstens) dann im Programm eingesetzt werden, wenn eine gewisse Zufälligkeit in der Programmausführung vorhanden war. Beispiel: Das Programm hat auf den Druck einer Taste vom Benutzer gewartet. Dieses Event kann man nutzen, um den Zufallszahlengenerator neu zu initialisieren. Aber hier gilt: Nicht übertreiben! Die Gefahr, die Qualität der Zahlen eher zu verschlechtern als zu verbessern, ist ziemlich groß!
    Zitat


    Was ich auch weggelassen hatte, war deine Beschreibung der Bitverschiebungen, die das Basic V2 bei RND ganz so vornimmt, wie du gesagt hast. :)


    Nun ja, wobei ich gerade mit diesen Verschiebungen von Bits nicht ganz sicher bin, was ich davon halten soll. Ich befürchte ja, dass die Zufallszahlen davon eher schlechter werden. Möglicherweise hat MS ja auch gemerkt, dass der Generator nicht gut ist, und wollte ihn dadurch (scheinbar) etwas verbessern?


    Gruß,
    - Spiro.

  • Zitat

    Originally posted by hannenz
    definiere ZUFALL... :nixwiss:


    Nichts einfacher als das: Zufall ist ein Ereigniss dessen Eintreffen und/oder Ausgang nicht eindeutig vorhersagbar ist. ;)


    "Echte" Zufälle gibt es auch in der Natur nur wenige, zB. beim radioaktiven Zerfall oder in der Quantenmechanik - Schrödingers Katze wäre ein schönes Beispiel.


    Ich finde, wenn es einen Computer gibt mit dem sich am ehesten echte Zufallszahlen erzeugen lassen, dann ist es der C64:


    Meine Idee: Einen Track einer Disk komplett löschen und dann mit Nullen beschreiben (ohne Sync) und dann wieder einlesen. Nicht nur, dass die Position ab der gelesen wird relativ zufällig wäre (durch die Gleichlaufschwankungen), sondern auch das Ergebniss welches die Hardware liefert ist zufällig (dazu: ohne Sync kein Framing). Diesen Wert kann man dann noch zusätzlich mit dem SID-Rauschen, einem Timer-Wert und dem Rasterstrahl verknüpfen. Mit dem Ergebniss wird der Timer dann initialisiert für die nächste Runde. Zudem könnte dieser Wert noch als Zähler für eine Verzögerungsschleife genutzt werden, erst dann wird der nächste Wert von Disk "gelesen".


    Damit liese sich ein Stream erzeugen, in dem es kaum Wiederholungen von Bytesequenzen geben dürfte.


    Also wenn das jemand vorhersagen könnte, dann weiss ich auch nicht weiter. ;)