【问题标题】:can rand() be used to generate predictable data?rand() 可以用来生成可预测的数据吗?
【发布时间】:2014-05-15 23:14:11
【问题描述】:

我的目标是生成 2D 或 3D 几何图形而不必将其存储在磁盘上,因此我的目标是拥有任何类型的功能,而不是根据小种子生成相同的值。我并不是要寻找随机值,但如果在给定相同种子时返回相同的“随机”垃圾数据,那就是我正在寻找的东西。

如果我给 srand() 相同的整数,我会从 rand() 中得到相同的序列。这是预期的功能吗?如果没有,是否有已知的标准函数可以做同样的事情?

虽然我在 ideone 和我的电脑上尝试过,得到了不同的结果,但我可以理解,这些函数的实现没有描述,所以解释一下。

【问题讨论】:

  • srand() 中的“s”字面意思是“种子”,所以你去吧,先生。
  • 永远不要依赖rand 来生成好的随机数据。它必须是确定的,仅取决于种子和前面调用的数量。
  • 计算机在可预测方面非常好,而在真正随机方面则不太好;您的观察是正确的,rand() 使用相同的种子值生成的数字序列是可重复的。但我不相信这种行为是有保证的。如果您需要可重复(即固定)的数字序列,我认为更好的选择是生成这些集合并存储它们。特别是如果您需要在各种系统上重复此操作。

标签: c++ math random probability


【解决方案1】:

如果我给 srand() 相同的整数,我会从 rand() 中得到相同的序列。这是预期的功能吗?

是的,见 7.20.2.2:

7.20.2.2 srand 函数

[...] 说明

srand 函数使用参数作为新的伪随机序列的种子 后续调用 rand 时将返回的数字。 如果 srand 被调用 相同的种子值,伪随机数序列将重复。

但是,这仅适用于 srand/rand 的相同实现。另一个实现可能不会使用相同的算法,因此不会产生相同的序列。

如果没有,是否有已知的标准函数可以做同样的事情?

嗯,这些函数是标准的,但只是在它们的行为上,而不是实际值(参见上面的实现注释)。您最好使用来自C++11 predefined random number generators 的特定生成器,因为它们是标准化的。

【讨论】:

    【解决方案2】:

    "如果我给 srand() 相同的整数,我会得到相同的序列 兰德()。这是预期的功能吗?”

    是的。

    如果你用相同的种子播种相同的随机数生成器,它将产生相同的结果。

    标准库 rand 及其所有变体通常实现为 Linear congruential generators。它们并不是真正随机的,也许更好地称为 psuedo-random

    您可能在不同的机器上看到不同的结果,因为它们使用不同的伪随机数生成算法,或者您没有提供固定的种子,在这种情况下,当前系统时间通常是默认种子。

    如果您需要一组固定的伪随机数据,则生成一次并存储。

    【讨论】:

    • 我为这些测试提供了相同的种子。 “存储它”:不,我的目标是减少内存占用
    • 我知道,它们存储在主板中。呵呵。
    【解决方案3】:

    答案是肯定的,如果你总是使用相同的实现和相同的种子,你会得到一个可重复的序列,尽管由于rand() 的质量可能很差,这可能是不明智的。
    不过最好在<random> 中使用C++ 随机数框架。它不仅允许跨实现的可重现序列,还提供了可靠地获得您真正想要的分布所需的一切。

    现在进入细节:

    rand 的要求是:

    • 生成伪随机数。
    • 范围是 0 到 RAND_MAX(最小值为 32767)。
    • srand() 设置的种子决定了返回的伪随机数序列。

    对于实现什么 PRNG 没有任何要求,因此每个实现都可以有自己的,尽管 Linear Congrueantial Generators 是最受欢迎的。

    在这个 dilbert strip 中提供了一个符合要求(尽管可以说是无用的)实现:

    http://dilbert.com/strips/comic/2001-10-25/

    或者对于喜欢 XKCD 的人(它是任何 C 或 C++ 库的完美插件;-)):

    为了完整起见,标准引号:

    7.22.2.1 rand 函数

    rand 函数计算范围为 0 到 0 的伪随机整数序列 RAND_MAX。
    [...]
    RAND_MAX 宏的值至少应为 32767。

    7.22.2.2 srand 函数

    srand 函数使用参数作为新的伪随机序列的种子 后续调用 rand 将返回的数字。如果 srand 然后用 相同的种子值,则应重复伪随机数序列。如果兰特是 在对 srand 进行任何调用之前调用,应生成相同的序列 就像第一次使用种子值 1 调用 srand 时一样。

    【讨论】:

      【解决方案4】:

      如果您使用相同的值作为随机数生成器的种子,它将产生相同的结果。您在不同的机器上看到了不同的结果,因为它们(可能)使用了不同的随机数生成算法。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-03-06
        • 1970-01-01
        • 2016-10-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多