【问题标题】:Why is the first random number always the same on some platforms in lua?为什么在 lua 的某些平台上第一个随机数总是相同的?
【发布时间】:2010-10-02 11:54:56
【问题描述】:

考虑以下 lua 代码 sn-p :

local time = os.time()
for _= 1, 10 do
    time = time + 1
    print('Seeding with ' .. time)
    math.randomseed(time)
    for i = 1, 5 do
        print('\t' .. math.random(100))
    end
end

在 Linux 机器上,结果如预期的那样是随机数。但似乎至少在Mac OS X上,改变种子后的第一个随机数总是一样的!

我猜这与 Lua 依赖 C rand() 函数生成随机数有关,但有人解释一下吗?

编辑:这是上述代码在 linux 机器上的输出摘录(即输出与预期一致):

$ lua test.lua
Seeding with 1232472273
    69
    30
    83
    59
    84
Seeding with 1232472274
    5
    21
    63
    91
    27
[...]

在 OS X 机器上,“Seeding with ...”之后的第一个数字始终是 66。

【问题讨论】:

  • 你在两台机器上使用相同的lua版本吗?可能是 Mac OS X 中的一个错误。
  • 是的,我用的是最新的lua版本。

标签: random lua


【解决方案1】:

Lua 的 random 曾经使用 C 的 rand(3)srand(3) 函数(see here)。更新:较新的 Lua 版本 use random(3) where available.

C90 标准和 POSIX 都建议使用 randsrand 的跨平台实现,这不是最好的。尤其是低位缺乏随机性。

Linux 等一些平台放弃了标准建议,转而采用更好的实施方式(例如 random(3))。

OS/X 仍然忠实于经典的 rand 实现,Lua 继承了它。

【讨论】:

  • 这仍然不能真正解释为什么他总是得到 66 作为第一个数字,但这是很好的信息。
  • 算法“不是最好的”是一种轻描淡写的说法;)它没有做它应该做的事情,而且完全没用和损坏。不,你不能争辩说“你不应该这样使用它”,程序员不应该被要求拥有这些知识。
  • 没有任何 C 标准,包括 C90,为 randsrand 定义任何类型的实现。他们只是指定函数应该做什么(返回伪随机数)。这些标准确实包括示例实现,但示例在 ISO 标准中不是规范性的——它们没有施加任何限制。允许 C 的实现使用他们想要的任何版本的randsrand,并且使用示例以外的定义绝对不是“不符合标准的”。我建议你改变你的措辞:)(例如,C89)。
  • @ChuckyEllison 够公平的!
【解决方案2】:

使用数字接近的种子多次调用 srand 通常是一个坏主意(尤其是使用时间值这样做更糟糕)。在很多情况下,第一个随机数的方差类似于种子的方差。在处理必须转换数字表示的脚本语言时,情况可能更是如此。

如果您将种子值更改得较大,是否会发生同样的情况?

【讨论】:

    【解决方案3】:

    正如其他人指出的那样,Lua 出于可移植性的考虑故意使用 C90 随机生成器——而 C90 RNG 并不是很好。

    如果您需要好的随机数,请使用一些 Lua 模块来获取它。例如,here 是 Lua 作者之一的 Mersenne Twister RNG 绑定。

    【讨论】:

      猜你喜欢
      • 2013-06-07
      • 1970-01-01
      • 1970-01-01
      • 2012-05-22
      • 1970-01-01
      • 1970-01-01
      • 2016-08-26
      • 1970-01-01
      相关资源
      最近更新 更多