直接使用系统时间获取随机数

时间:2011-01-08 20:31:59

标签: time random

我不得不从数组中返回一个随机元素,所以我想出了这个占位符:

return codes[(int) (System.currentTimeMillis() % codes.length - 1)];

现在我想起来,我很想在实际代码中使用它。 Random()播种机无论如何都使用系统时间作为种子,所以为什么不直接使用那个时间呢?作为奖励,我可以摆脱许多RNG的非随机低位的担忧。这个黑客回来咬我? (如果相关,则该语言为Java。)

4 个答案:

答案 0 :(得分:2)

这是一个糟糕的主意!甚至不要考虑它!连续调用这个本土的“伪随机数生成器”将相互关联得如此之强,以至于你可能只是使用一个简单的计数器。 (如果你错过了,我不推荐。)

编辑添加:顺便说一句,正如您编写的那样,您的数组索引有时会为-1。这也是一个糟糕的主意。

答案 1 :(得分:2)

使用内置的java.util.Random。 Effective Java (第二版,第215页)的第47项将此作为一个示例,说明为什么您应该更喜欢标准库而不是自己编写。它首先解释Math.abs(rnd.nextInt() % n是一种不好的方法,因为它不会产生真正的随机分布,而只需使用rnd.nextInt(n)。它继续说:

  

编写用于纠正这三者的random方法的版本   你必须要了解公平   关于伪随机数的数量   发电机,数论和二   补充算术。

     

...

     

您不必关心nextInt(int)如何工作的详细信息。一位具有算法背景的高级工程师花费了大量时间来设计,实现和测试这种方法,然后向该领域的几位专家展示,以确保它是正确的。然后,该库经过了beta测试,发布,并在数十年的大部分时间里被数百万程序员广泛使用。在该方法中尚未发现任何缺陷,但如果要发现缺陷,则将在下一次修复中修复。通过使用标准库,您可以利用编写它的专家的知识以及在您之前使用它的人的经验。

应该注意的是,尽管该示例并未使用与您建议的代码完全相同的代码,但对于您的示例来说更是如此。取随机整数的余数会使分布偏斜,但至少它具有随机性的一些外观。只是改变时间是一个更糟糕的方法。

您低估了伪随机数生成器的复杂性。你所建议的方法的问题在于,不仅分布可能不是随机的,而且它实际上是可预测的。有一些真实世界的例子,黑客利用伪随机数生成器,可预测的种子在扑克中作弊。 构建安全软件(Viega和McGraw,2002)包含讨论这些问题的完整章节。

  

这是一个很好的例子,说明在实践中如何破坏可怜的PRNG。 1999年,Cigital的软件安全组发现了由ASF Software,Inc。分发的Texas Hold'em Poker实施中的一个严重缺陷。该漏洞允许一个作弊的玩家计算出每个手牌的确切牌组。时间。这意味着使用该漏洞的玩家知道每个对手手中的牌以及组成翻牌的牌(牌组在下注后面朝上放置牌)。骗子可以“知道何时抓住他们并且每次都知道何时折叠他们”。恶意攻击者可以使用该漏洞利用来吸引无辜玩家的实际资金而不会被抓获。 (第238页)

以下是讨论随机性复杂性的两个问题:

这是一篇只有几周时间(但有一个非常蹩脚的标题)的论文,描述了如何利用PRNG的可预测种子来攻击PHP的会话生成算法:

答案 2 :(得分:0)

我能想到的唯一原因是:如果系统时钟总是返回16的倍数(例如,这可能发生在Windows XP机器上),并且你的数组的长度恰好是16?

答案 3 :(得分:0)

首先开发标准库类通常是有充分理由的。

虽然尝试编写自己的代码来解决学术环境中的问题可能会很酷,但在商业环境中,最好使用经过验证的库和技术,这些库和技术不太可能在您的应用程序中创建不需要的行为。 / p>

如果您开始使用您的技术,我强烈建议您编写完整的测试用例来测试边界条件和大量数据点。这将帮助您在生成代码之前对其进行调试。