随机数w /种子作用非确定性

Ale*_*x Z 6 random algorithm lua android coronasdk

我已编程多年了,我现在提出的问题可能是我遇到的最奇怪的问题之一.

我的应用程序中有一段代码随机生成一系列令牌,有三种可能的类型,比如A,B或C.

所以10个代币可能是ABCCAAABAC.

在代码块的开头,随机数生成器种子初始化如下:

math.randomseed(seed)
math.random()
Run Code Online (Sandbox Code Playgroud)

现在,不出所料,当种子值保持不变时,我总是得到相同的令牌序列,因为随机生成代码以确定的方式执行.好吧,几乎总是.

实际上,在极少数情况下,出乎同样的种子,我会得到一个不同的随机序列.然后它在我知道之前恢复正常.你可能在想 - 啊,副作用,这可能是一个状态相关的问题,其中生成随机令牌序列的代码块利用一个变量来改变它调用的次数random()(例如).但是,我99%肯定我控制了所有明显的副作用.代码块中只有少数位置可以访问外部状态,并且它们都保持不变.

情节变得更加浓厚 - 这个问题在我一直在构建的应用程序的Android部署上才显而易见.不可否认,这是一个罕见的错误,我似乎无法可靠地重复它.因此它也可能出现在iOS部署中.但我还没有在其他平台上遇到它.我不妨提一下,我正在通过Corona SDK使用lua脚本来开发应用程序.

我已经多想了这个问题,并将其缩小到几个可能性:

  1. 与使用相同随机数生成器的另一个线程交互,我不知道
  2. (这在lua中甚至可能吗?)某种堆损坏会导致奇怪的副作用
  3. 我搞砸了,有一些该死的明显的外部状态参考,我在很长时间的调试中都错过了

所有这些最痛苦的方面是bug的不可重复性.大多数情况下,代码块在给定重复种子的情况下完全确定.然后就好像存在一个非确定性阶段,然后在一段未知的时间后再次消失.我想在这里挑选一位专家的大脑.

这可能会发生什么?此外 - 由于我在Android部署中只看到了这个特定问题,因此可能会有任何特定于平台的特定问题吗?

作为参考,这是完整的代码块.它实际上生成具有两个随机属性(三种颜色之一,三种形状之一)的标记,但这并不意味着问题的本质.

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
Run Code Online (Sandbox Code Playgroud)

小智 1

https://docs.coronalabs.com/api/library/math/random.html指出:

该函数是 ANSI C 提供的简单伪随机生成器函数 rand 的接口。不能保证其统计特性。

这让我想知道其他程序是否使用相同的功能。这可能会导致这些冲突,同时也或多或少地解释了为什么它们只是有时发生。