【发布时间】:2010-11-17 01:44:47
【问题描述】:
我知道 Random 类可以生成伪随机数,但有没有办法生成真正的随机数?
【问题讨论】:
-
什么是
truly random?即使是掷骰子也不是随机的。滚动取决于高度、施加的力、风等。你的大脑无法处理这些数据。
我知道 Random 类可以生成伪随机数,但有没有办法生成真正的随机数?
【问题讨论】:
truly random?即使是掷骰子也不是随机的。滚动取决于高度、施加的力、风等。你的大脑无法处理这些数据。
这里的答案有两个主要方面。您应该注意一些非常重要的微妙之处...
RNGCryptoServiceProvider 是 BCL 中 Crypto API 的一部分,应该可以为您完成这项工作。从技术上讲,它仍然是一个生成的伪随机数,但“随机性”的质量要高得多——顾名思义,它适用于加密目的。
还有其他具有高质量伪随机生成器的加密 API。 Mersenne twister 等算法非常流行。
与 BCL 中的 Random 类相比,它明显更好。例如,如果您将Random 生成的数字绘制在图表上,您应该能够识别出模式,这是一个很弱的信号。这主要是因为该算法仅使用固定大小的种子查找表。
要生成真正的随机数,你需要利用一些自然现象,比如核衰变、微观温度波动(CPU温度是一个比较方便的来源)等等。然而,这要困难得多,当然需要额外的硬件。我怀疑实用的解决方案(RNGCryptoServiceProvider 或类似的)应该可以很好地为您完成这项工作。
现在,请注意,如果您确实需要真正的随机数,您可以使用Random.org 等服务,它会生成具有非常高随机性/熵的数字(基于atmospheric噪音)。数据可免费下载。尽管如此,这对于您的情况来说可能是不必要的复杂,尽管它确实为您提供了适合科学研究之类的数据。
最终选择权在您,但至少您现在应该能够做出明智的决定,了解 RNG 的各种类型和级别。
【讨论】:
RNGCryptoServiceProvider。如果您愿意描述上下文,我可以确认这是否足以满足您的使用需求。
简短回答:仅使用 C#(即仅使用纯数学构造)无法直接生成 真正随机数。
long(er) 答案:仅通过使用能够生成“随机性”的外部设备(例如 white noise generator or similar)并将该设备的输出捕获为伪随机数生成器 (PRG) 的种子。这部分可以使用 C# 来完成。
【讨论】:
只有在真正随机的物理输入设备为随机函数提供种子的情况下,才能生成真正的随机数。
科学界仍在争论(并且可能会持续很长时间)是否存在任何物理的和真正随机的东西。
伪随机数生成器是次优的,最好的很难预测。
【讨论】:
正如约翰·冯·诺依曼 (John von Neumann) 开玩笑说的那样,“任何考虑用算术方法产生随机数字的人,当然都处于一种犯罪状态。”
【讨论】:
线程是旧的并已回答,但我想我还是会继续。这是为了完整性,人们应该知道一些关于 Random 在 c# 中的事情。
至于真正的随机,你能做的最好的事情就是使用像 salsa20 或 RC4 之类的“安全伪随机生成器”(有时是这样)。它们通过了一系列测试,“高效”的对手试图将它们与随机区分开来。这会带来一定的成本,并且对于大多数用途来说可能是不必要的。
c# 中的随机类在大多数情况下都非常好,它具有看起来随机的静态分布。但是 random() 的默认种子是系统时间。因此,如果您在“同时”获取大量随机数,它们将使用相同的种子并且将是相同的(“随机”是完全确定的,不要让它欺骗你)。由于随机类的缺点,相似的系统时间种子也可能产生相似的数字。 处理这个问题的方法是给你自己设置种子,比如
Random random = new Random((int)DateTime.Now.Ticks & (0x0000FFFF + x));
如果你创建了一个循环来获取一堆随机数,那么 x 是你增加的某个值。
此外,使用 c# 对新变量(如 NextDouble() 进行随机扩展)有助于处理随机数,在这种情况下,将它们放入区间 (0,1) 以变为 unif(0,1),这种情况发生的是一个分布,您可以将其插入统计公式以创建统计中的所有分布。
【讨论】:
看看使用像 Yarrow 或 Fortuna 这样的算法和熵累积。这些算法的重点在于,它们通过了解过去的数字和用于生成它们的算法来跟踪熵,作为可用于预测未来数字的理论信息内容的度量;他们使用密码技术将新的熵源折叠到数字生成器中。
您仍需要外部随机数据源(例如hardware source of random numbers),无论是击键时间、鼠标移动时间、硬盘访问时间、CPU 温度、网络摄像头数据或股票价格,还是不管怎样——但无论如何,你会不断地将这些信息混合到熵池中,这样即使真正的随机数据速度很慢或质量很低,也足以让事情以一种不可预测的方式进行。
【讨论】:
我正在讨论基于 twitter 或其他社交网站之一构建一个随机数生成器。基本上使用 api 来提取最近的帖子,然后使用它来播种高质量的伪随机数生成器。它可能并不比随机关闭计时器更有效,但看起来很有趣。此外,它似乎是人们发布到 Twitter 上的大多数内容的最佳用途。
【讨论】:
我一直很喜欢这个想法,因为 60 年代的复古外观:
【讨论】:
计算机中没有“真正的”随机性,一切都基于其他东西。对于一些(可行的)生成伪随机数据的方法,请尝试诸如 HD 温度池、CPU 温度、网络使用率(数据包/秒)以及可能的网络服务器点击/秒之类的方法。
【讨论】:
There is no "true" random in computers,在现实生活中都没有。除非“随机”是指“我暂时无法预测的事情”。
没有办法用计算机生成真正的随机数。真正的随机性需要一个外部源来监控某些自然现象。
也就是说,如果您无法访问这样一个真正随机数的来源,您可以使用这样的“穷人”过程:
这个两步过程应该可以在一定程度上提高结果的随机性,而无需外部输入。
这是一个用 C++ 实现上述算法的示例库:http://www.boost.org/doc/libs/1_39_0/libs/random/random-generators.html
【讨论】:
只是为了澄清大家说 C# 或您的计算机上没有可用的 True RNG 是错误的。多核处理器本质上是真正的 RNG。非常简单地通过利用处理器旋转,您可以生成没有可识别模式的布尔值。从那里,您可以通过将布尔值用作位并通过将位相加来构造数字来生成您想要的任何数字范围。
是的,这比纯数学解决方案慢很多,但纯数学解决方案总会有一个模式。
public static bool GenerateBoolean()
{
var gen1 = 0;
var gen2 = 0;
Task.Run(() =>
{
while (gen1 < 1 || gen2 < 1)
Interlocked.Increment(ref gen1);
});
while (gen1 < 1 || gen2 < 1)
Interlocked.Increment(ref gen2);
return (gen1 + gen2) % 2 == 0;
}
【讨论】:
此代码将返回一个介于min 和max 之间的随机数:
private static readonly Random random = new Random();
private static readonly object syncLock = new object();
public int RandomNumber(int min, int max)
{
lock (syncLock)
{ // synchronize
return random.Next(min, max);
}
}
用法:
int randomNumber = RandomNumber(0, 10); // a random number between 1 and 10
【讨论】:
Random类生成的数字只有Pseudo Random。如果您阅读了一些回答这个问题的答案,您应该更好地了解 OP 的含义。