Lua math.random() 函数经常返回 0

我正在使用 Lua 进行分布和直方图的制作,在这个过程中我需要生成介于 01 之间的随机数。由于我需要生成成千上万个这样的随机数并对每个随机数的对数进行计算,所以我发现了之前使用 math.random() 函数从未遇到过的问题:这个函数生成了出乎意料的多的 0 值。由于它生成了带有 14 个小数位的数字,我期望每次调用该函数时大约有一次在 10^14 次中生成一个 0,但实际上我发现在调用 math.random() 函数 100,000 次时,会得到至多 5 或 6 个 0这里是我制作的一个简单测试。首要问题是,由于我必须计算这些随机值的对数,因此 math.log(0) 返回 -inf,这会干扰大多数变量,如平均值和标准偏差。

这不是一个严肃的项目,我可以很容易地通过多种方法解决这个问题,甚至可以在获得 0 值时重新计算一个随机数,但我想知道这里到底出了什么问题。我在 Python 中尝试了同样的方法,没有遇到这个问题。我还发现 math.random() 不会返回小于 0.00001 的任何数字(除了 0),这让我认为这是一个舍入问题。

那么到底出了什么问题,如何获得一个更均匀分布的 [0,1) 区间的随机数生成器?感谢任何帮助!

点赞
用户7504558
用户7504558

你可以尝试删除值为0并移动范围,像这样:

local function rnd()
   local base = 100000
   local x = (math.random(0,base+1)-1)/base
   if x<0 then return rnd() end
   return x
end

local function test(n)
  local k=0
  local x
  math.randomseed(os.time())
  for i=1,n do
    x = rnd()
    if x==0 then k=k+1 end
  end
  print("k=",k)
end

test(100000)

如果我们将 base 值降低到10,那么你就能看到一个可以接受的限制值为 0 和 1 的数量。

2019-09-12 07:38:22
用户4984564
用户4984564

我完全无法复制你的结果!

这是我的测试代码:

math.randomseed(os.time())

function test(n)
  local k = 0
  for i=1, n do
    if math.random() == 0 then
      k = k + 1
    end
  end
  return k / n
end

for i=1,6 do
  print(string.format("%8.4f %%", test(1e7) * 100))
end

而且结果是:

PUC Lua 5.3.5

  0.0000 %
  0.0000 %
  0.0000 %
  0.0000 %
  0.0000 %
  0.0000 %

LuaJIT 2.1.0-Beta3

  0.0000 %
  0.0000 %
  0.0000 %
  0.0000 %
  0.0000 %
  0.0000 %

作为一个简单的解决方案,我建议这样做

local function random()
  local result = math.random()
  return result>0 and result or random()
end

另外,只需返回 result>0 and result or 1,因为 1 永远不会被 math.random() 返回,所以如果你不介意在其中有一些 1 的话,那是另一种选择。

2019-09-12 07:49:40
用户5932641
用户5932641

所以问题可能是由于Windows PRNG引起的,正如Egor Skriptunoff所指出的那样。我仍然很好奇的是为什么没有生成介于00.00001之间的数字。无论如何,我现在正在使用LuaJIT,问题得到了解决(无需解决措施)!谢谢大家!

2019-09-12 16:04:07