2009-01-20 17 views
5

Betrachten Sie den folgenden lua-Code-Snippet:Warum ist die erste Zufallszahl auf einigen Plattformen in lua immer gleich?

local time = os.time() 
for _= 1, 10 do 
    time = time + 1 
    print('Seeding with ' .. time) 
    math.randomseed(time) 
    for i = 1, 5 do 
     print('\t' .. math.random(100)) 
    end 
end 

Auf einem Linux-Rechner, das Ergebnis ist, wie erwartet, Zufallszahlen. Aber zumindest unter Mac OS X scheint die erste Zufallszahl nach dem Ändern des Samens immer gleich zu sein!

Ich denke, das hängt damit zusammen, dass Lua auf die C rand() - Funktion zum Generieren von Zufallszahlen angewiesen ist, aber hat jemand eine Erklärung?

EDIT: Hier ist ein Extrakt aus der Ausgabe des oben genannten Codes auf einem Linux-Maschine (dh der Ausgang wird wie erwartet):

$ lua test.lua 
Seeding with 1232472273 
    69 
    30 
    83 
    59 
    84 
Seeding with 1232472274 
    5 
    21 
    63 
    91 
    27 
[...] 

Auf einer OS X-Maschine, die erste Zahl nach „Animpfen mit ... "war immer 66.

+0

Verwenden Sie die gleichen Lua-Versionen auf beiden Maschinen? Vielleicht ein Bug im Mac OS X. –

+0

Ja, ich benutze die neueste lua-Version. – Wookai

Antwort

4

Lua's Zufall verwendet, um C's rand(3) und srand(3) Funktionen (see here) zu verwenden. UPDATE: neuere Lua Versionen use random(3) where available.

Sowohl der C90-Standard als auch POSIX schlagen eine plattformübergreifende Implementierung von rand und srand vor, die nicht die beste ist. Es fehlt insbesondere die Zufälligkeit in den unteren Bits.

Einige Plattformen wie Linux bewegten sich von der Standardempfehlung zu einer besseren Implementierung (z. B. random(3)).

OS/X bleibt der klassischen Implementierung rand treu und Lua erbt es.

+1

Das erklärt immer noch nicht wirklich warum er immer 66 als erste Nummer zurückbekommt, aber es sind gute Informationen. –

+1

Dass der Algorithmus "nicht der Beste ist" ist eine ziemliche Untertreibung;) Er macht nicht was er soll und ist völlig nutzlos und kaputt. Und nein, Sie können nicht argumentieren, dass "Sie sollten es nicht so verwenden", Programmierer sollten nicht verpflichtet sein, dieses Wissen zu haben. – Sire

+2

Keiner der C-Standards, einschließlich C90, definiert irgendeine Art von Implementierung für "rand" oder "srand". Sie geben einfach an, was die Funktionen tun sollen (geben Pseudozufallszahlen zurück). Die Standards enthalten eine Beispielimplementierung, aber Beispiele sind in ISO-Normen nicht normativ - sie enthalten keine Einschränkungen. Implementierungen von C können beliebige Versionen von "rand" und "srand" verwenden, und andere Definitionen als das Beispiel sind definitiv nicht "nicht konform". Ich schlage vor, Sie ändern Ihre Formulierung :) (z. B. [C89] (http://port70.net/~nsz/c/c89/c89-draft.html#4.10.2)). –

-2

Wenn Sie den gleichen Seed verwenden, erhalten Sie die gleiche Reihe von Zahlen aus der C rand() -Funktion, aber Sie sollten eine andere Reihe von Zahlen jedes Mal, seit Sie scheinen zu erhalten verwende die aktuelle Zeit als Seed.

Edit: Ich nehme an, ich sollte auf meine Antwort näher eingehen. Wenn Sie beim Seeding mit os.time() keine zufällige Zeichenfolge erhalten, erhalten Sie möglicherweise nicht das, was Sie von diesem Funktionsaufruf erwarten. Welche Werte erhalten Sie von os.time()?

Edit # 2: Auch, was ist die Ausgabe von diesem Block des Codes?

+0

Ich bin mir der Tatsache bewusst, dass die Verwendung desselben Samens die gleiche Folge von Pseudozufallszahlen ergibt. Meine Frage bezieht sich auf die Tatsache, dass die erste generierte Zahl mit verschiedenen Seeds auf einigen Plattformen identisch ist. – Wookai

2

Es ist generell eine schlechte Idee srand mehrere Male mit Samen zu nennen, die numerisch nahe sind (und vor allem schlecht zu tun, mit Zeitwerte). In vielen Fällen ist die Varianz der ersten Zufallszahl ähnlich der Varianz der Samen. Wenn es sich um eine Skriptsprache handelt, die Zahlenrepräsentationen konvertieren muss, kann es sogar noch mehr sein.

Tritt das Gleiche auf, wenn Sie den Startwert um einen größeren Betrag ändern?

1

Wie andere angemerkt haben, verwendet Lua absichtlich C90 Zufallsgenerator für Portabilität Sake - und C90 RNG ist nicht sehr gut.

Wenn Sie gute Zufallszahlen benötigen, verwenden Sie ein Lua-Modul, um es zu bekommen. Zum Beispiel ist here eine Mersenne Twister RNG-Bindung von einem der Lua-Autoren.