2011-01-08 36 views
0

我不得不从一个数组返回一个随机元素,所以我想出了这个占位符:直接使用系统的时间来获得随机数

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

现在比我想起来了,我很想用它在真实的代码。无论如何,播种机使用系统时间作为种子,所以为什么不直接使用这个时间?作为奖励,我免于担心许多RNG的非随机低位。这黑客回来咬我? (语言是Java的,如果这是相关的。)

回答

2

使用内置了java.util.Random。 有效的Java(第二版,第215页)的项目47把它提出来作为为什么你应该更喜欢使用您自己的标准库的例子。它首先解释Math.abs(rnd.nextInt() % n是一种不好的方法,因为它不会产生真正的随机分布,您应该简单地使用rnd.nextInt(n)来代替。它接着说:

要编写一个版本的random方法可以解决这三个 惹麻烦的,你必须知道一个公平 量大约伪随机数 发电机,数论,以及两个的 补算术。

...

你不必与nextInt(int)是如何做的工作细节关心自己。具有算法背景的高级工程师花费了大量的时间来设计,实施和测试该方法,然后将其展示给该领域的多位专家,以确保它是正确的。然后,图书馆进行了测试,发布,并在数十年的大部分时间里被数百万程序员广泛使用。该方法中尚未发现任何缺陷,但是如果发现缺陷,将在下一步中修复。通过使用标准库,您可以充分利用编写它的专家的知识以及在您之前使用它的人的经验。

应当注意的是,即使例如不完全使用相同的代码,你是在暗示一个,它更真实的你的榜样。取一个随机整数的其余部分偏离分布,但至少它有一些随机性的出现。只是调整时间是一种更糟的做法。

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

下面是一个很好的例子,说明如何在实践中破坏可怜的PRNGs。 1999年,Cigital的软件安全组发现了德克萨斯Hold'em Poker的一个严重缺陷,该软件由ASF Software,Inc.分发。该漏洞使得作弊的玩家可以计算出每只手在实际使用时的确切甲板时间。这意味着使用该漏洞的玩家可以知道每个对手手中的牌以及组成翻牌的牌(在下注一轮后,牌面朝上)。骗子可以“知道什么时候握住他们,知道何时每次折叠他们”。一个恶意攻击者可以利用这个漏洞在没有被捕获的情况下欺骗无辜的玩家。 (页238)

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

这是一份文件,只有几周大(但一个真正蹩脚的标题),描述了如何利用PRNG的可预测种子来攻击PHP的会话生成算法:

0

唯一的原因,我能想到的反对是这样的:如果系统时钟总是返回16的倍数(这可以在Windows发生的XP机器,例如)什么,和你的阵列恰好是16的长度?

0

通常有很好的理由,标准库类已经在第一时间得到了发展。

虽然它可能是凉着编写自己的代码,以解决学术环境问题,在商务场合进行实验,最好使用久经考验库和不太可能在应用程序中创建不必要的行为的技术。

如果您在使用你的技术设置,我会强烈建议你写详尽测试用例来测试边界条件和大量的数据点。这将帮助您在代码投入生产之前调试代码。

2

这是一个可怕的想法!别想它!连续调用这个自制的“伪随机数生成器”将被强烈关联,以至于你可能只需要使用一个简单的计数器。 (其中,如果你错过了,我不推荐)

编辑补充:顺便说一句,正如你编码它,你的数组索引偶尔会是-1。这也是一个可怕的想法。