android - 具有种子作用的随机数生成非确定性

标签 android algorithm random lua coronasdk

我从事编程多年,现在提出的问题可能是我遇到过的最奇怪的问题之一。

我的应用程序中有一段代码随机生成一系列标记,具有三种可能的类型,假设是 A、B 或 C。

所以 10 个 token 可能是 ABCCAAABAC。

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

math.randomseed(seed)
math.random()

现在,毫不奇怪,当种子值保持不变时,我总是得到相同的标记序列,因为随机生成代码以确定性方式执行。嗯,几乎总是。

实际上,在极少数情况下,给定相同的种子,我会突然得到不同的随机序列。然后不知不觉就恢复正常了。您可能在想 - 啊,副作用,这可能是一个与状态相关的问题,其中生成随机标记序列的代码块利用一个变量来改变它调用 的次数random()(例如)。但是,我 99% 确定我已经控制了所有明显的副作用。代码块中只有少数地方访问外部状态,并且它们都保持不变。

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

我对这个问题进行了深思熟虑,并将其缩小为几种可能性:

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

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

这里可能发生了什么?此外 - 是否有可能针对此特定问题发生任何特定于平台的问题,因为我只在 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

最佳答案

https://docs.coronalabs.com/api/library/math/random.html状态:

This function is an interface to the simple pseudo-random generator function rand provided by ANSI C. No guarantees can be given for its statistical properties.

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

关于android - 具有种子作用的随机数生成非确定性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35282688/

相关文章:

java - 将 ExecutorService 与合并排序的多线程版本一起使用

使用 malloc 和指针在 C 中创建 2 个随机矩阵

c - 如何从文本文件中选择随机问题?

java - 如何在 Fragment 中动态添加 TableRow?

java - 用于读/写 IPv6 地址范围以实现快速查找的高效数据结构是什么?

java - 将 ImageView 设置为 android fragment 中的 URL

c++ - STL 的 'partial_sum' 有什么实际用途?

batch-file - 如何在cmd批处理文件中创建随机列表

java - Android Socket fatal error

java - 如何在recyclerView中为textview(非常非常长的文本)自动水平滚动设置动画