如何“检查”函数是否真的给出了随机结果?

时间:2011-06-22 10:08:20

标签: function random verify

如何确保函数真的是随机的或尽可能接近概念?另外,随机和伪随机有什么区别?最后,可以使用哪些算法/源来生成随机数?

P.S:也问这个,因为使用ORDER BY RAND() LIMIT 1的MySQL语句没有给出令人信服的结果。

7 个答案:

答案 0 :(得分:16)

关于随机的事情是你不能告诉来自随机函数的返回是否是随机的。

XKCD

...或...

Dilbert

适当随机使用可以真正随机的内容,例如white noise。伪随机数通常根据数学公式或预先计算的表来计算。 Linear congruential generator是一种生成它们的流行方法。

要获得真正的随机数,您通常希望与外部源接口,其中某些内容已经有机地生成。这称为True Random Number Generator

答案 1 :(得分:10)

阿罗哈!

有几种方法和工具可用于测试随机性。这些应用于从待测试的发生器收集的一组数字上。也就是说,您根据生成的一组数据测试生成器

在计算中,尤其是IT安全性,我们通常希望拥有一个符合统一随机过程的生成器。有许多不同的过程,但我猜这是一个你想要的统一过程。

NIST已经发布了几个文档,其中包含伪随机数生成器的建议以及如何测试它们。查看NIST文件SP 800-22和SP 800-20。

正如其他人指出的那样。如果你想要一个真随机数发生器(TRNG),你需要收集物理熵。这些光源的例子是放射性衰变,宇宙辐射,熔岩灯等。最好你想要难以操作的光源。 IETF有一个RFC有一些很好的建议,请参阅RFC 4086 - 安全随机源: http://tools.ietf.org/html/rfc4086

您通常采取的措施是从一个或多个(最好是一个以上)来源收集熵。然后对收集的数据进行过滤(白化),最后用于定期播种良好的PRNG。用不同的种子,自然。

这是大多数现代优质随机发生器的工作原理。一个熵收集器,用于使用诸如对称密码(例如AES)或散列函数之类的加密原语创建的PRNG。例如,参见Schneier的随机生成器Yarrow / Fortuna,在FreeBSD中使用了修改后的形式。

回到你关于测试的问题。正如有人指出Marsaglia已经制作了一套很好的测试,这些测试已在DIEHARD测试中编纂。现在Dieharder测试中有更多的测试: http://www.phy.duke.edu/~rgb/General/dieharder.php

Dieharder是一个很好的工具,可以让你很有信心,提供给它的大量数字(从你的发电机收集)是随机的(质量好)或不是。运行Dieharder很容易,但需要一些时间。

随机性的原位测试很难。您通常不希望在系统中实现Dieharder。你可以做的是实现一些应该检测病态病例的简单检测器。我通常建议:

  • 等值长度。一个简单的计数器,只要RNG生成的两个连续值不同,就会复位。然后,当您认为计数器显示RNG已损坏时,您需要定义阈值。如果您看到1000万个相等的值,并且值空间大于一个值(您看到的那个),您的RNG可能无法正常工作。 Esp,如果值正在查看是边缘值之一。例如0x00000 ....或0xfffff ...

  • 中位数价值。如果您在生成一百万个值并且具有均匀分布后,其中值很大程度上倾向于其中一个值空间边缘,而不是接近中间,则可能也会出现问题。

  • 差异。如果你在生成数百万个值之后没有看到接近值空间的MIN和MAX的值,而是有一个狭窄的生成值空间,那么也有些不妥。

最后。由于您希望使用良好的PRNG(例如基于AES),建议的原位测试可能会应用于熵源。

我希望在某些方面有所帮助。

答案 2 :(得分:4)

您可以应用统计测试来查看给定数字序列是多么可能是独立的,相同分布的(iid)随机变量。

看看George Marsaglia的A Current View of Random Number Generators。特别是,请看第6-12节。这提供了对这些测试的介绍,然后是几个可以应用的测试。

答案 3 :(得分:2)

是的,我们无法保证随机数实际上是随机数 关于伪随机数:是的它们似乎是随机的(最初用于加密)(伪随机函数),当发送加密文本和陷阱之间的邪恶时,消息认为他得到的加密文本是随机的,但是消息是从某个函数计算的,而且你将使用相同的函数和键获得相同的消息(如果有的话,所以没有 - 它们不是随机的,只是看起来像是随机的,因为你不能创建它生成的原始文本/数字例如散列函数(md5,sha1)和加密技术(des,aes等)。

答案 4 :(得分:1)

如果数字随机,则无法预测它。因此,任何生成“随机”数字的算法都会生成伪随机数,因为始终可以使用在“随机化”期间使用的使用过的种子或值来生成相同的“随机”数字序列。真正的随机数可以通过例如骰子滚动生成,但不能通过计算机算法生成。

答案 5 :(得分:1)

理论计算机科学教导计算机是确定性机器。每个算法都以相同的方式运行,因此您必须改变种子。但是计算机应该从哪里获得随机种子?从外部设备? CPU温度(变化不大)?

答案 6 :(得分:-5)

要测试一个返回随机数的函数,你应该多次调用它,看看每个数字的返回次数。

例如

For i := 1 to 1000000 do // Test the function 1.000.000 times
begin
   RandomNumber := Rand(9); // Random numbers from 0 to 9
   case RandomNumber of
      1 : Returned0 := Returned0 + 1;
      1 : Returned1 := Returned1 + 1;
      1 : Returned2 := Returned2 + 1;
      1 : Returned3 := Returned3 + 1;
      1 : Returned4 := Returned4 + 1;
      1 : Returned5 := Returned5 + 1;
      1 : Returned6 := Returned6 + 1;
      1 : Returned7 := Returned7 + 1;
      1 : Returned8 := Returned8 + 1;
      1 : Returned9 := Returned9 + 1;
   end;
end

WriteLn('0: ', Returned0);
WriteLn('1: ', Returned1);
WriteLn('2: ', Returned2);
WriteLn('3: ', Returned3);
WriteLn('4: ', Returned4);
WriteLn('5: ', Returned5);
WriteLn('6: ', Returned6);
WriteLn('7: ', Returned7);
WriteLn('8: ', Returned8);
WriteLn('9: ', Returned9);

每个随机输出的完美输出应该是相等的数字。类似的东西:

0: 100000
1: 100000
2: 100000
3: 100000
4: 100000
5: 100000
6: 100000
7: 100000
8: 100000
9: 100000