2

关于RNG,我有三个问题。

首先是哪些数据可用作种子。我一直在利用时间,但必须有其他容易获得的种子。

c++中有哪些容易获得的种子?

如果我根据从 RNG 中出来的下一个值以随机间隔重新播种 RNG,并从问题 1 的答案中随机选择种子,这会创建一个更难预测并因此更随机的伪随机链吗?

最后,在 c++ 中获得一个范围内的随机数的最佳方法是什么?我一直在使用模数运算符,但我想要在范围内均匀分布的东西,而不是像 AI 决策那样偏向高或低。

4

4 回答 4

3
  1. 这取决于你需要什么rand。对于很多用途,time是完全足够的。对于其他人来说则更少。我通常会从 Unix 机器上读取四个字节,如果 不可用则/dev/random恢复。更有效的解决方案是使用更高分辨率的计时器,并在进程或机器 ID 等内容中进行散列。time/dev/random

  2. 除非您使用类似的方法,否则重新播种可能不会改变太多/dev/random。大多数其他可用值都是可以预测的。

  3. 如果RAND_MAX是范围的倍数,则模可以正常工作。如果不是,唯一的解决方案是丢弃值:你有一个总值 RAND_MAX + 1,你需要n. 并且没有可能的映射将所有RAND_MAX + 1值映射到n每个 并且具有相同数量的输入n。通常的解决方案是:

    整数限制 = (RAND_MAX + 1) - (RAND_MAX + 1) % n;
    int 结果 = rand();
    而(结果>=限制)
        结果 = 兰德();
    返回结果%n;

(我在这里假设您正在寻找范围内的结果 [0...n)。这RAND_MAX + 1不会溢出。)

最后,如果您担心随机值的质量,请注意许多实现rand()并不是特别好。您可能想要切换到增强随机生成器之一。

于 2011-06-22T12:46:41.967 回答
2

你应该看看boost::random

记住:

  • 为什么需要随机数——为了安全,还是为了随机过程?
  • “更随机”是什么意思?
  • 如果您根据一种算法重新设定种子,并且该算法比底层 RNG 更可预测,那么您的情况会比开始时更糟。如果您的种子只是 32 位值,那么即使是真正随机的种子源也会使事情变得更糟而不是更好!
  • 如果您需要“混合”来自随机源的额外随机性,最好通过 XOR 来做到这一点:即维护一小块真正的随机数,并将它们循环异或到 RNG 的输出中 - 而不是偶尔重新播种,偶尔会重新生成该垫。这样,您就不会丢弃 RNG 有价值的内部状态。或者,如果您可以访问 RNG 内部,请使用真正的随机源偶尔通过类似的机制旋转一些位。

我希望您可以简单地使用boost::mt19937,但这实际上取决于应用程序。

于 2011-06-22T12:19:13.247 回答
1

RNG 的一个容易获得的种子是任何时间函数。种子不需要是随机的,只要每次启动程序都不同,这就足够了。试图使伪随机数“更随机”是一项有点愚蠢的努力。如果需要,那么生成器就不值得了。
此外,除非用真正的随机噪声定期播种,否则无论如何您都不会使输出“更加随机”,如果您定期播种真正的随机噪声,那么只有种子才是真正随机的,其他值仍然是确定性的,并且总共有与此生成器生成的任何其他序列具有相同的统计属性。

如果偏斜分布不可接受,则在非二次幂范围内获取数字的通常实现看起来有点像:

range = high - low;

while((r = rand()) > range) {}

r += low;

模数和乘法/除法具有众所周知的歪斜和溢出问题。

不过,如果是如你所说的人工智能决策,我敢说,如果一个结果的可能性比另一个结果高 1%,我敢说没有人会注意到。因此,简单地使用模可能就足够了,具有确定的时间,而且非常简单。另请注意,您始终可以选择一个适用于模数的范围。

于 2011-06-22T12:43:31.920 回答
0

对于大多数应用程序来说,时间已经足够了,如果您需要更好的随机数,那么您应该查看提供此类功能的特定库。

对于范围生成,以下内容不会扭曲结果:

int random = rand() * RANGE / RAND_MAX;

于 2011-06-22T12:18:39.083 回答