【问题标题】:rand() produces the same result on each function call (with srand(time(0))rand() 在每个函数调用中产生相同的结果(使用 srand(time(0))
【发布时间】:2017-10-15 00:52:16
【问题描述】:

我有一个类的成员函数,它应该在一个范围内生成一个随机数。为此,我使用了 rand() 函数。该函数生成一个随机数,如下所示:

    unsigned seed;
    seed = time(0);
    srand(seed);
    std::cout << "Random Number: "<< rand() << std::endl;

函数在两个不同的对象上调用。结果是:

Random Number: 1321638448
Random Number: 1321638448

每次我调用它时都是一致的。我做错了什么?

【问题讨论】:

  • 在程序中多次重新设定随机发生器的种子是非常不寻常的 - 通常你先做一次,然后再也不碰它。而time 通常具有一秒的分辨率,所以如果你在同一秒内以这种方式生成两个随机值,你会期望看到这个。
  • 如果我应该只播种一次,我应该在我的主播中进行吗?我认为我不应该在类构造函数中这样做,因为它会被调用两次。
  • 刚刚做了上面的,它工作!谢谢!
  • John,您可以在构造函数中进行延迟初始化,例如 static bool first = true; if (first) { first = false; srand(time(nullptr)); }main 建议可能更好,因为您的类可能不是 only 使用的东西随机数。
  • 如果你标记它 [c++] 考虑使用来自 here 的东西来代替

标签: c++ random


【解决方案1】:

(将我的评论转换为答案)。

对于大多数应用程序,您只需要在运行程序的过程中为rand 播种一次。多次播种需要您获得不同的随机种子,而且很容易搞砸。

在您的情况下,time 函数通常返回具有秒级别分辨率的内容(尽管this isn't actually required by the standard)。因此,如果您在同一秒内两次调用time,您可能会得到相同的值。这可以解释为什么你会得到重复值:你用相同的值播种随机器两次,然后立即查询它以获取随机数。

对此的最佳解决方案是只为随机发生器播种一次。通常,您会在 main 中这样做。

如果您确实想多次为随机发生器播种,请确保您使用的种子几乎是随机的。否则,您将面临发生这种情况的风险。

【讨论】:

    【解决方案2】:

    伪随机数生成器基本上必须通过一组统计测试,以确保它们作为一组数字“足够随机”。但当然,它实际上并不是随机的。用一些seed 调用srand(seed) 基本上会生成一组数字,如果通过这些测试,它们看起来“足够随机”。

    通过多次使用相同的seed 调用srand(seed),您实际上是一次又一次地生成相同的集合并获得其中的第一个值。

    您调用srand(seed) ONCE,然后调用rand() 以获取随机数集中的下一个值。或者您需要每次使用不同的(随机)种子调用srand(seed)

    如果你在 linux 上,你也可以使用/dev/urandom 来获得一个随机数——内核一直在从环境中获取信号/噪声来为其生成“熵”,据说它比算法更好伪随机数生成器。

    【讨论】:

    • 每次都不是同一个种子。 time(0) 以 32 位或 64 位整数类型给出当前时间
    • 我听到你在说什么,但正如上面的评论者解释的那样,快速连续调用 time(0) 实际上返回相同的数字。
    • 另外,OP 不调用 srand(time(0)),OP 调用 srand(seed),其中种子在某些时候被设置为 time(0)。
    【解决方案3】:

    srand 函数只能在程序中调用一次(大多数情况下,不是所有情况下)。如果你想重新播种,你应该使用不同的种子号。因为rand() 函数是伪随机数生成器。换句话说,rand() 会为您提供一个计算得出的数字。

    在 C++11 之后,您可以使用很多强大的随机数生成库。见:http://en.cppreference.com/w/cpp/numeric/random

    【讨论】:

    • "srand 函数只能在程序中调用一次。"这是一个太难的陈述,这使得它不真实。在极少数情况下需要为随机数生成器重新播种。虽然我承认你很可能会从事编程职业,但从未遇到过这些情况。
    • @user4581301 喜欢多线程的情况?哦,我什至不想想象……
    • 请注意pcg-random.org 的库提供与&lt;random&gt; 相同的接口,但在许多方面都更好。
    • 你知道吗?我从未在多线程程序中使用过srand/rand。在 C++ 11 之后必须查看它是否是线程安全的。看起来不能保证。这些天来,任何需要重新播种的情况,几乎可以肯定您使用的是更好的随机数生成器。
    猜你喜欢
    • 1970-01-01
    • 2016-05-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-30
    相关资源
    最近更新 更多