2016-02-09 7 views
6

Ich habe für viele Jahre programmiert, und die Frage, die ich jetzt vorstelle, ist wahrscheinlich einer der seltsamsten, die ich gestoßen bin.Zufallszahl gen w/Samen nichtdeterministisch

Es gibt einen Code-Block in meiner app, die zufällig eine Folge von Token erzeugt, mit drei möglichen Typen, sagen wir A, B oder C.

So 10 Token könnte ABCCAAABAC sein.

Zu Beginn des Blocks des Codes wird der Zufallszahlengenerator Samen wie so initialisiert:

math.randomseed(seed) 
math.random() 

Nun, wenig überraschend, wenn der Wert Samen konstant bleibt, ich die gleiche Folge von Token immer bekommen, weil der Zufallserzeugungscode wird deterministisch ausgeführt. Nun, fast immer.

Tatsächlich, in seltenen Fällen, aus heiterem Himmel, werde ich eine andere zufällige Reihenfolge mit dem gleichen Samen erhalten. Dann ist es wieder normal, bevor ich es weiß. Sie denken wahrscheinlich - ah, Nebenwirkungen, dies ist wahrscheinlich ein Zustand bezogenen Problem, wobei der Code-Block, der die zufällige Reihenfolge der Tokens generiert verwendet eine Variable, die ändert, wie oft es ruft random() (zum Beispiel). Allerdings bin ich zu 99% sicher, dass ich für alle offensichtlichen Nebenwirkungen kontrolliert habe. Es gibt nur wenige Stellen im Code-Block, die auf den externen Zustand zugreifen und alle konstant bleiben.

Die Handlung verdichtet sich noch mehr - dieses Problem ist mir nur bei einer Android-Bereitstellung der App aufgefallen, die ich erstellt habe. Zugegeben, das ist ein seltener Fehler, und ich kann es nicht zuverlässig wiederholen. Es könnte also auch in den iOS-Bereitstellungen vorhanden sein. Aber ich muss es noch auf anderen Plattformen finden. Ich kann auch erwähnen, dass ich Lua Scripting über das Corona SDK verwende, um die App zu entwickeln.

ich dieses Problem viel Gedanken gegeben haben, und haben es bis auf wenige Möglichkeiten verengt:

  1. Interaktion mit einem anderen Thread, die die gleiche Zufallszahlengenerator verwendet, die ich von
  2. nicht bewusst bin (ist dies überhaupt möglich in lua?) Eine Art Heapbeschädigung führt zu seltsamen Nebenwirkungen
  3. ich habe vermasselt und es gibt einige verdammt offensichtlich Bezug auf die äußere Zustand, den ich über viele Stunden Debuggen verpasst haben

Der schmerzhafteste Aspekt ist die Unwiederholbarkeit des Fehlers. Meistens verhält sich der Codeblock bei einem wiederholten Seed vollkommen deterministisch. Dann ist es so, als gäbe es eine Phase von Nichtdeterminismus, die sich nach einer unbekannten Zeit wieder auflöst. Ich würde gerne die Köpfe eines Experten hier auswählen.

Was könnte hier vor sich gehen? Außerdem - ist es möglich, dass es plattformspezifische Probleme mit diesem speziellen Problem gibt, da ich es nur bei Android-Installationen gesehen habe?

Als Referenz ist hier der vollständige Block des Codes. Es erzeugt tatsächlich Token mit zwei zufälligen Eigenschaften (eine von drei Farben und eine von drei Formen), aber das bedeutet nicht viel in Bezug auf das Wesen des Problems.

math.randomseed(currentRandomSeed) 
math.random() 

local tokenListPlan = {} 

-- randomly assign weighting distribution 
local thresh1, thresh2 
while (true) do 
    local s0 = math.random(1, 99) 
    local s1 = math.random(1, 99) 
    local c0 = s0 
    local c1 = s1 - c0 
    local c2 = 100 - c1 - c0 
    if (c0 >= eng.DEVIATION_THRESHOLD and c1 >= eng.DEVIATION_THRESHOLD and c2 >= eng.DEVIATION_THRESHOLD) then 
     thresh1 = c0 
     thresh2 = c0 + c1 
     break 
    end 
end 

-- generate tokens (deterministic based on seed) 
for i = 1, sortedCountTarget do 
    local token 
    local c = 1 

    local rnd = math.random(1, 100) 
    if (rnd < thresh1) then -- skewed dist 
     c = 1 
    elseif (rnd < thresh2) then 
     c = 2 
    else 
     c = 3 
    end 

    if (paramGameMode == eng.GAME_MODE_COLOR) then 
     local rnd46 = math.random(4, 6) 
     token = {color = c, shape = rnd46} 
    elseif (paramGameMode == eng.GAME_MODE_SHAPE) then 
     local rnd13 = math.random(1, 3) 
     token = {color = rnd13, shape = c + 3} 
    else 
     local rnd13 = math.random(1, 3) 
     local rnd46 = math.random(4, 6) 
     token = {color = rnd13, shape = rnd46} 
    end 

    tokenListPlan[#tokenListPlan + 1] = token 
end 
+0

Wo genau setzen Sie den Randomseed? Es kann sein, dass in Android die Randomseed-Einstellung Zeile aus irgendeinem Grund mehr als einmal ausgeführt wird. – muratgu

+0

Kurz vor dem Codeblock (nichts dazwischen) bearbeite ich den Beitrag, um weniger eindeutig zu sein. Leider kann ich nicht sehen, wie es mehr als einmal ausgeführt werden könnte, vor allem nicht sporadisch ... –

+2

In einigen Fällen feuert math.random mehr als nur die erwartete Menge während der Laufzeit dieses Codes? Versuchen Sie, es in eine Funktion einzufügen, die eine Schließung verwendet, um den Betrag zu zählen, der aufgerufen wurde. Sehen Sie, ob sich das ändert, wenn Sie andere Ergebnisse erhalten. – warspyking

Antwort

1

https://docs.coronalabs.com/api/library/math/random.html Zustände:

Diese Funktion ist eine Schnittstelle zur einfachen Pseudozufallsfunktion rand Generator von ANSI C bereitgestellt wird, kann keine Garantien für seine statistischen Eigenschaften gegeben werden.

Das lässt mich fragen, ob andere Programme die gleiche Funktion verwenden. Das könnte zu diesen Konflikten führen, aber auch mehr oder weniger erklären, warum sie nur manchmal vorkommen.