ruben: random in widgets

Hallo Selfhtml-Gemeinde,

ich weiß nicht, ob euch allen das in Mac OS X Tiger implementierte Dashboard bekannt ist. Ist nix neues, gibt es auch für Windows unter dem Namen Konfabulator. Nunja unter OS X sind das also kleine DHTML-Programme die simple Aufgaben erledigen sollen.
Ein Problem, wenn man diese konstruiert ist allerdings das die Math.random-Funktion nicht wie erwartet funktioniert. Da sie anscheinend immer mit dem gleichen Wert geseeded wird, so bald das Dashboard aufgerufen wird, generiert man immer die gleiche Sequenz von Zahlen. Deswegen sind alle Widget-Schreiberlinge auf der Suche nach dem Zufall. Ich habe mich dem Club mal angeschlossen und habe folgende Funktion gebaut:
function rnd(max){
      var d = new Date()
      var f=  d.getMilliseconds()/(1000/max);
      var rand = Math.floor(f);
      return rand;
      }
Die ist besser als das meiste, was ich bisher hatte, habe sie allerdings noch nicht so ausgiebig getestet. Der Nachteil sind halt die Millisekunden. Eigentlich würde es nichts ausmachen, da man nicht weiß, welche Millisekunde grade ist, wenn man einen neuen Prozess auslöst. Da ich in meinem Zitat-Spucker allerdings so lange neue Zufallszahlen errechnen lasse, bis eine gefunden ist, die noch nicht dran war, ist es nicht so gut. (ich habe keine Ahnung, wie schnell mein Computer ist, aber er generiert bestimmt mehrere Zufallszahlen in der Millisekunde, oder? Also generiere ich unnötig viele, bis ich eine neue raus finde.

Hat jemand eine Ahnung, wie ich gute Zufallszahlen mit JS generieren kann, ohne auf die im Dashboard eben nicht funktionierende Math.random() Funktion zurückzugreifen? Ich hab nicht viel Ahnung von Widgets, aber ich weiß, dass man über bestimmte Funktionen auf die Systemfunktionen von Mac OS X zugreifen kann (und auf das Internet, aber ich will ein Offline-Widget). Ich hab aber keine Ahnung, wo ich in einem System den Zufall finde :-)

Kann mir jemand helfen? Am liebsten wäre mir, was JS basiertes, damit ich es verstehen kann :-/
Vielen Dank im Voraus,
Ruben

  1. Hallo ruben,

    der Trick bei vielen Zufallszahlgeneratoren ist, dass sie die Startzahl aus der Zeit berechnen. Wenn du die immer gleiche Startzahl deines Zufallszahlgenerators nicht beeinflussen kannst, wäre ein Weg, den Generator einige Male vorlaufen zu lassen. Die Zahl der Vorläufe kannst du dann ja aus den Millisekunden (evtl. geteilt durch 10 oder so) errechnen.

    Gruß, Jürgen

    1. Hallo Jürgen,

      Naja, da er bei der gleichen Anzahl Maximalstellen, die stets gleiche Sequenz erzeugt, würde das nicht viel Sinn machen oder? Oder meinst du eine zufällige Anzahl von Vorläufen? Mir erscheint das Resourcenverschwendung. Gibt es keine Möglichkeit sich selbst eine Zufalls-Funktion zu konstruieren?
      Und was gäbe einen besseren Seed ab als die Millisekunden?
      Danke,
      Ruben

      1. Hallo ruben,

        die Idee war, eine willkürliche Anzahl von Vorläufen in der Größenordnung 10 zu haben und diese z.B. aus der Uhrzeit zu ermitteln. Danach kannst du den Zufallszahlgenerator normal verwenden. Dein Problem mit der immer gleichen Startzahl könntest du so umgehen.

        Das Programmieren eines Zufallszahlgenerators ist recht einfach. Man muss nur eine Zahl, z.B. die vorherige Zufallszahl mit einer genügend großen und genügend "krummen" Zahl multiplizieren. Die anschließende Modulofunktion übernimmt dann der Rechner, da man bei Integeroperationen bei Bereichsüberschreitung den Zahlenraum nicht verlässt. Größte Zahl plus eins gleich kleinste Zahl. Als Formel:

        Random_neu=Random_alt*fak.

        Danach muss nur noch normiert werden.

        Hier kommen jetzt aber zwei Probleme:

        Den Multiplikator "fak" kenne ich nicht auswendig. Hier könnte aber das Internet weiterhelfen.

        Der Zufallszahlgenerator funktioniert nur bei Integermultiplikation. Ob Javascript so etwas kann oder automatisch auf Fließkomma mit Mantisse und Exponent umschaltet, musst du ausprobieren.

        Ich wurde dir aber empfehlen, den eingebauten Generator zu nehmen. Die Performance ist bestimmt besser und einige 10 Vorläufe durften nicht ins Gewicht fallen.

        Gruß, Jürgen

        1. Random_neu=Random_alt*fak.
          Danach muss nur noch normiert werden.
          Hier kommen jetzt aber zwei Probleme:
          Den Multiplikator "fak" kenne ich nicht auswendig. Hier könnte aber das Internet weiterhelfen.

          Verstehe ich ehrlich gesagt nicht recht, durch Multiplikation mehrerer Zufallszahlen erhält man also neue Zufallszahlen? Klingt logisch

          Der Zufallszahlgenerator funktioniert nur bei Integermultiplikation. Ob Javascript so etwas kann oder automatisch auf Fließkomma mit Mantisse und Exponent umschaltet, musst du ausprobieren.

          Ich bin in der 10. Klasse des Gymnasiums und verstehe nur Bahnhof, aber wie du dir sicherlich denken kannst, will ich auch um diese schöne Jahreszeit nichts davon wissen.

          Ich wurde dir aber empfehlen, den eingebauten Generator zu nehmen. Die Performance ist bestimmt besser und einige 10 Vorläufe durften nicht ins Gewicht fallen.

          Ich würde ja gerne, doch das ist leider unmöglich, da in diesen Widgets diese Funktion den Fehler hat, dass sie bei jedem System-Neustart die exakt gleiche Sequenz liefert, d.h.die ersten zehn Anläufe sind immer gleich. Man kann genau vorausbestimmen, welcher "Zufallswert" an wievielter Stelle generiert wird. Was ich machen könnte, wäre folgendes: So oft Zufallszahlen generieren lassen, wie es grade MIllisekunden gibt, das wäre allerdings Resourcen-belastend. Gibt es eine Möglichkeit die Random-Funktion zu seeden, ihr also einen Wert zu geben, anhand dessen sie Zufall generieren soll?
          Was sagst du zu der Funktion, die ich am Anfang veröffentlicht hatte?

          Danke vielmals,
          Ruben

          1. Hallo ruben,

            die Zufallszahlgeneratoren erzeugen immer eine Folge von Pseudozufallszahlen, die von der Startzahl abhängt, ansonsten aber recht zufällig wirkt. Weil bei dir die Startzahl immer gleich ist, ist natürlich auch die Folge immer gleich. Da du auf die Startzahl keinen Zugriff hast, war meine Idee, die Folge "irgendwo" beginnen zu lassen und dieses "Irgendwo" durch einige 10 bis 100 Vorläufe zu ermitteln. Das dauert bestimmt deutlich weniger als 100 Millisekunden.

            Wenn du es selbst machen willst, versuch mal folgendes:

            Nimm irgendeine Startzahl, z.B. die Zeit Modulo irgendwas, und für jede neue Zufallszahl nimmst du die vorherige mit 65539 mal, und anschließend modulo 2^32, also

            var zuf_z=12345; // oder irgendetwas aus der Zeit
            zwei_hoch_32=Math.pow(2,32);
            function zuf() {
             zuf_z=((zuf_z*65539)%zwei_hoch_32);
             return zuf_z/zwei_hoch_32;
            }

            die Modulodivision ist hier notwendig, da Javascript den Datentyp "32-bit-Integer" nicht kennt.

            Gruß, Jürgen