【问题标题】:How do the "random" generators in different languages (i.e. Java and C++) compare?不同语言(即 Java 和 C++)的“随机”生成器如何比较?
【发布时间】:2013-02-04 08:12:47
【问题描述】:

尽管标题很奇怪,但我想问一个合理的问题:哪个方法生成的数字更随机:Java 的 Random() 类或 Math.random(),还是 C++ 的 rand()

我听说 PHP 的 rand() 很糟糕,也就是说,如果你映射它的结果,你可以清楚地看到一个模式;遗憾的是,我不知道如何用 C++ 或 Java 绘制地图。

另外,只是出于兴趣,C# 呢?

【问题讨论】:

  • C++ 有<random>。我想我读过一次,虽然它可能完全是伪造的记忆,但 C# 使用 MT。
  • 看到模式对于人类大脑来说是很自然的。事实上,如果你没有看到模式,我会担心随机函数的随机性。 1 0 0 0 0 1 1 1 0 0 0 0 0 可能比 1 0 1 0 1 0 0 1 0 1 0 1 0 0 随机得多
  • @BasvandenBroek:这里的问题是模式是可预测的。这不仅仅是一个块,而是完整的随机序列。
  • 定义“更随机”。它们之间的区别通常是用作发电机的任何东西的周期长度。显然java.util.Random 使用线性同余生成器,与 C 中的rand 类似。C++11 引入了mt19937(Mersenne Twister)等等。不过,它们在底层都是确定性的(因此是 PRNG 中的伪)。
  • @Thomas 为什么会这样?这在 Stack Overflow 上很少发生。

标签: java c++ random


【解决方案1】:

Java 和 C++ 都生成伪随机数:

  • 足以胜任任何非统计学家或密码学家的任务(a);或
  • 严重不适合这两类人。

老实说,除非您 属于这些类别之一,否则伪随机数生成器就可以了。

Java 还具有 SecureRandom,它声称提供加密类非确定性(我无法评论该论点的真实性),而 C++ 现在具有比 rand() 更广泛的随机数生成能力- 详情请见<random>

特定的操作系统可能会为随机数生成器提供熵源,例如 Windows 下的 CryptGenRandom 或 Linux 下的读取 /dev/random。或者,您可以通过使用随机事件(例如用户输入时间)来添加熵。


(a)实际上可能包含非统计学家或密码学家的其他工作类型的痕迹:-)

【讨论】:

  • C++11 中存在 头文件,它为分布和随机数生成器提供了一整套函数。所以对 C++ 的支持似乎很强大。不过我不知道 Java。
【解决方案2】:

java.util.Random(由Math.random() 内部使用)使用Linear congruential generator,这是一个相当弱的RNG,但对于简单的事情来说已经足够了。对于重要的应用程序,应该使用java.security.SecureRandom

我不认为 C 或 C++ 语言规范禁止用于 rand() 的算法,但大多数实现也使用 LCG。 C++11 添加了新的 API,可产生更高质量的随机性。

【讨论】:

  • 这在 C++11 中发生了显着变化。见here
  • @juanchopanza:添加了新的 API,但 rand() 的算法仍未指定。
  • 对,但关键是现在不仅仅是rand()
【解决方案3】:

可以在网络上找到一个非常好的文档,由世界范围内的随机数生成器专家之一完成。

Here is the document

文档的第一部分是对测试的描述,除非您真的感兴趣,否则您可以跳过它。从第 27 页开始,有许多生成器的不同测试结果,包括 Java、C++、Matlab、Mathematica、Excel、Boost,...(在正文中进行了描述)。

似乎Java的生成器好一点,但两者都不是世界上最好的。 C++11 的 MT19937 已经好很多了。

【讨论】:

  • 第 27 页,我想您可能从“Article 22 / 27”中获得了 page#,但 每个 页面上都有第 22 页。为您更改了:-) 无论如何,+1 用于查找一些硬数据。
  • @paxdiablo 哎呀!谢谢!
【解决方案4】:

PHP 使用种子。如果种子在两个不同时间相同,则 rand() 函数将始终输出相同的内容。 (例如,这对于令牌来说可能非常糟糕)。 我不知道 C++ 和 Java,但没有真正的随机性,这使得质量难以评估。安全性不能依赖这些功能。

【讨论】:

  • 到处都是一样的。所有数学算法都是确定性的,并且给定相同的种子会产生相同的输出。真正的随机数只能由软件产生。
  • 我完全同意,这就是我刚才所说的。
  • 完全不相关。标准始终以当前时间播种。如果它具有足够的分辨率并且 PRNG 充分依赖于它的种子,那么这对于许多应用程序来说都是稳健的。甚至安全,如果时间=种子不能被对手猜到。
  • 想象一下我们使用 microtime() 函数作为种子,就像许多程序员一样 (mt_srand((double)microtime()*1000000);),有很多方法可以创建漏洞(例如,参见 suspekt.org/2008/08/17/mt_srand-and-not-so-random-numbers
【解决方案5】:

我不知道任何语言中随机数是真正随机的 - 我确信这样的事情存在,但一般来说,它是“你把种子放进去,你就会得到种子给出的序列”。如果你想制作一个简单的“射击”游戏、基本的扑克游戏、家用轮盘赌模拟器等,这很好。但是如果你有钱依赖于真正随机的游戏(例如,你正在给钱基于某些序列的结果)或您的秘密文件依赖于您的随机数,那么您肯定需要一些其他机制来查找随机数。

还有一些“真正的”随机数生成器。他们不提供种子,因此基于您上次获得的数字的可预测性很低。我并不是说它是零,因为我不确定你是否可以通过以未使用的无线电频率、放射性衰变或任何最新的生成真随机数的方法来采样无线电波来获得它。

【讨论】:

    猜你喜欢
    • 2020-03-10
    • 1970-01-01
    • 2018-04-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多