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:
- Interaktion mit einem anderen Thread, die die gleiche Zufallszahlengenerator verwendet, die ich von
- nicht bewusst bin (ist dies überhaupt möglich in lua?) Eine Art Heapbeschädigung führt zu seltsamen Nebenwirkungen
- 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
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
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 ... –
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