Lua,随机有多随机?

3

我需要验证我们Lua实现中随机数生成器的能力。

以下是我的解决方案...

 for i = 1,10000 do                         -- I hope that's ten thousand

 X = math.random(0,9)

 if     X == 0 then This_Many_0 = This_Many_0 + 1
 elseif X == 1 then This_Many_1 = This_Many_1 + 1
 elseif X == 2 then This_Many_2 = This_Many_2 + 1
 elseif X == 3 then This_Many_3 = This_Many_3 + 1
 elseif X == 4 then This_Many_4 = This_Many_4 + 1
 elseif X == 5 then This_Many_5 = This_Many_5 + 1
 elseif X == 6 then This_Many_6 = This_Many_6 + 1
 elseif X == 7 then This_Many_7 = This_Many_7 + 1
 elseif X == 8 then This_Many_8 = This_Many_8 + 1
 elseif X == 9 then This_Many_9 = This_Many_9 + 1

 else               Bogus_Alert = True      -- Better not happen

 end                                        -- End the big if/elseif block

 The_Interim_Sum = The_Interim_Sum + X      -- Keep a running sum

 end                                        -- This is the i loop

我把结果打印出来了,这就是它们...
 Running
 Number of times we got 0  ...  1019
 Number of times we got 1  ...  979
 Number of times we got 2  ...  954
 Number of times we got 3  ...  1006
 Number of times we got 4  ...  995
 Number of times we got 5  ...  999
 Number of times we got 6  ...  989
 Number of times we got 7  ...  1000
 Number of times we got 8  ...  1042
 Number of times we got 9  ...  1017
 The sum of the ten thousand random numbers was 45303
 The average of those numbers was 4.5303
 End

这些数字符合我的期望,即平均数非常接近4.5,并且每个单独数字的分布也接近于一千。
更重要的是,有了这样的数字,我可以说,是的,生成器确实做得很好,真正生成了一万个随机数字,它们确实是随机的。
问题在于:我的老板说,如果机器真的做好了它的工作,真的给我们提供了随机数字,那么每个数字的分布应该是均匀的;即,在一万次迭代中,每个数字应该恰好出现一千次。
我尝试在使用基于 X = math.random(0,9) 的循环之前添加了 math.randomseed(os.time()) ,但结果更加偏差,不是更接近。
我去掉了 math.randomseed(os.time()) 这一行,再次运行测试,得到了平均值为4.5007(这是我见过的最好结果)。
那么,我发现了什么?任何东西?没有吗?伪随机数生成器真的只是一个伪随机数生成器?每个人都知道这一点。
我证明了这个伪随机数生成器是否与我们所期望的随机程度相当?
我有理由担心使用这些值吗?我将在一个例程中尝试使用错误的数字。全部范围对于测试每种情况来说都太大了。我猜想,如果分配得当,则进行16K次射击将使我确信芯片正在正确地处理(故意提供的)值。
(读者注意:我在对多处理器系统进行V&V,我的Lua脚本模拟了我们尚未拥有的系统部件的行为。)
有没有办法让Lua使用math.random()函数在这种情况下生成恰好一千个每个数字?
如果可以,那真的会是随机的吗?

2
为什么您会期望真正的随机分布产生每个数字的相等数量?虽然均匀分布是最可能的特定结果,但您看到它的可能性仍然远小于看到许多不相等数字的分布之一。 - Mankarse
5
你的老板在概率论方面缺乏必要的知识。 - Egor Skriptunoff
好的,那么,对于进行V&V测试,我现在所拥有的是足够随机的吗? - User.1
1
真正的熵几乎只有在保护恶意意图方面才有用。也就是说,在安全应用中。很可能为了验证您的系统,使用math.randomos.time作为种子就足够了。有时候,预定义的种子甚至更好。如果您认为这还不够,那么对您的系统进行正式证明可能更有用。 - dualed
@dualed 你的评论非常明智。给你点赞 +1。 - User.1
3个回答

4

首先,在使用math.random()之前,您需要运行一次math.randomseed(),并且最好丢弃前几个随机数,因为在某些实现中,前几个随机数不太随机,请参阅Lua math.random not working了解详细信息。

math.randomseed(os.time())
math.random(); math.random(); math.random()

其次,即使你抛一枚完美平衡的硬币一千次,你通常不会得到恰好500次正面和500次反面。只是获得正面的概率大约为500。如果实验做了很多次,你会期望正面的平均值为500,但每次都不会精确地达到500。

第三,是的,math.random()是一个随机数生成器。事实上,你不能仅使用计算机生成真正的随机数。Lua math.random()在内部使用C库函数rand()。而且C rand()函数并不是一个好的随机数生成器。如果随机性很重要,可以使用一些更好的方法来实现,例如C++随机引擎或Linux上的dev/random等。


我看到了那个,但是在我的实验中我忽略了前几个数字。谢谢你提醒我。我不应该在凌晨3点和4点还在工作。我要去睡觉了。 - User.1
1
std::uniform_int_distribution 不是一个随机数生成器,它只是对随机数进行后处理,使得生成的分布符合某些分布属性。但它并不会增加任何熵到结果中(例如,将 rand 值提供给分布仍然会产生低质量的随机性)。C++ 中实际的随机数生成器被称为引擎(std::random_devicestd::mt19937)。请注意,通常您需要正确的引擎和适当的分布才能获得所需的数字。 - ComicSansMS
FYI,不存在所谓的真正随机数。任何伪随机数生成器都会产生一些差异。 - dns

4

3

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接