【问题标题】:RANDOM Number Generation in CC中的随机数生成
【发布时间】:2010-04-19 10:26:16
【问题描述】:

最近我开始开发一个简单的游戏。它是我开发的早期版本的改进版本。游戏的成功很大程度上取决于不同模式下的随机数生成:

MODE1 - 真正随机模式

myRand(min,max,mode=1);

  • 应该返回一个随机整数 b/w min & max。

MODE2 - 伪随机:令牌出袋模式

myRand(min,max,mode=2);

  • 应该返回一个随机整数 b/w min & max。还应在内部跟踪返回的值,并且在所有其他值至少返回一次之前不得再次返回相同的值。

MODE3 - 伪随机:人类模式

myRand(min,max,mode=3);

  • 应该返回一个随机整数 b/w min & max。随机化不应该是纯粹的数学随机,而是用户感知的随机。 How Humans see RANDOM

* 假设代码是时间关键的(即欢迎任何性能优化)

* 伪代码可以,但我正在寻找 C 中的实现。

* 请保持简单。一个函数就足够了(这就是我要找的)

谢谢

【问题讨论】:

  • 你不能在电脑上生成真正的随机数!嗯,你可以例如。通过这个设备cryptography.com/resources/whitepapers/IntelRNG.pdf
  • @Yacoby。是的 rand() 并不是真正随机的。因此,我正在尝试实现我自己的 myrand() 函数,如上所示。
  • 对于模式 2,说在给出所有数字之前永远不要重复,这不是随机的。随机意味着您无法预测一个数字是否会重复。通过说他们不能重复,你放弃了一些关于后续数字的可能性的东西。因此并不是真正随机的。可能是你想要的,但它不能被称为随机。
  • 所以 mode2 实际上是关于返回数字 min、min+1、...、max 的随机排列,而不是随机数序列
  • @Tesserex 那是一种伪随机模式。它用于像谁想成为百万富翁的测验这样的情况,在这种情况下,同一个问题不应该在一个会话中被问两次。我想我现在已经透露了我游戏的一部分...... ;-)

标签: c random


【解决方案1】:

首先,研究 Mersenne Twister。这应该是您解决问题的良好基础。

模式1:直接使用值。鉴于这些值是 32 位的,取决于 min 和 max 的范围,模 (max-min+1) 可能就足够了,尽管如果这个间隔不是 2 的幂,则存在一个小的偏差。否则,您可以将该值视为 0 到 1 之间的浮点值,并且需要一些额外的操作。可能还有其他解决方案可以让整数均匀分布,但我还没有研究过这个具体问题。维基百科在这里可能会有所帮助。

模式 2:使用一个用 min..max 填充的数组,然后对其进行随机播放。按顺序返回打乱后的值。当你通过数组时,重新填充并重新洗牌。

模式 3 是最复杂的。少量随机值显示集群,即,如果您计算不同值的出现次数,则您有一个平均值,并且计数通常高于或低于该平均值。据我了解您的链接,人类期望随机性具有所有计数的平均值。因此,根据它们与平均计数的距离,计算出现次数并赋予不同值更高的概率。简单地使用多数组重用模式 2 可能就足够了,例如使用一个大小为 (max-min+1) 的 10 倍的数组,用 10x min、10x min+1 等填充它,然后随机播放。然后,每整整 10 轮,您的计数完全相等。

在模式 3 上编辑:

假设您有 min=1 和 max=5。你计算出现次数。如果它们都具有相同的概率(应该使用好的随机生成器),那么每个值出现的概率为 0.2,因为概率加起来为 1.0:

Value Occur Probability
1     7x    0.2
2     7x    0.2
3     7x    0.2
4     7x    0.2
5     7x    0.2
Average: 7x

但是现在假设 3 只出现了 5 次,而 5 出现了 9 次。如果要保持均匀分布,则 3 必须成为更高的概率才能赶上平均发生率,而 5 必须成为较低的概率才能在所有其他值赶上之前不会增长得这么快。尽管如此,所有个体概率加起来必须为 1.0:

Value Occur Probability
1     7x    0.2
2     7x    0.2
3     5x    0.3
4     7x    0.2
5     9x    0.1
Average: Still 7x

不同的出现也应该有不同的概率,这取决于它们与平均值的距离:

Value Occur Probability
1     10x   0.05
2     4x    0.35
3     5x    0.3
4     7x    0.2
5     9x    0.1
Average: Still 7x

实现起来并不简单,而且很可能很慢,因为随机生成器仍然提供相等的概率,所以修改后的模式 2 可能是一个足够好的选择。

【讨论】:

  • @安全。谢谢你。您能否详细说明 Mode3。尤其是部分......“计算出现次数并赋予不同值更高的概率”
【解决方案2】:

第一步,去阅读 Knuth

【讨论】:

  • 确实,只要浏览一下他的伪随机数生成方法和算法,你应该很容易解决这些问题。
  • @chris 我确实通过了 KNUTH www-cs-faculty.stanford.edu/~uno/programs/rng.c 但我特别在寻找任何指针来实现可以在所有三种模式下运行的 myrand() 函数。
【解决方案3】:

如果 max-min = 2^N-1,则可以对模式 2 使用线性反馈移位寄存器。这种随机发生器产生具有 N 位内部存储的 2^N-1 个数字的重复序列。更详细的解释和代码见http://en.wikipedia.org/wiki/LFSR

【讨论】:

  • 序列不应该重复。即名称编号不应连续返回两次;那不是随机的。此外,传递给 myrand() 的 max 和 min 有时可能会在对函数的连续调用之间发生变化。所以LFSR不是一个可行的解决方案...
【解决方案4】:

人类可感知与第一种模式相同,除了可以任意拒绝 2、5、10 的倍数的结果。

如果我要求一个随机数并得到 5 或 10,我会认为它不够随机。

【讨论】:

    猜你喜欢
    • 2010-11-29
    • 2012-03-18
    • 2015-07-19
    • 1970-01-01
    • 2019-05-15
    • 1970-01-01
    相关资源
    最近更新 更多