【问题标题】:srand() + rand() with local scope具有本地范围的 srand() + rand()
【发布时间】:2015-08-09 16:17:26
【问题描述】:

我有一个像这样调用 srandrand 的函数:

void foo() {
   int seed = some_operation();
   std::srand(seed);
   int value = std::rand();
   // Do something with random value
}

但是,我不想更改 rand 的全局状态。那么获取随机数的最简单方法是什么?

要求:

  • 随机数必须是基于种子的确定性
  • C++11 没问题
  • foo 应该是线程安全的
  • 不应修改 rand 的全局状态

编辑:

有一个 stackoverflow question 询问如何生成随机数。然而,被接受的answer 展示了如何使用慢速 std::random_device 生成真正唯一的随机数。我只需要一个使用固定种子的简单生成器。

【问题讨论】:

标签: c++ c++11 random scope thread-safety


【解决方案1】:

C++11 没问题

然后使用新的pseudorandom number library:

#include <random>

int foo() {
    int seed = some_operation();
    std::minstd_rand rand(seed);
    int value = rand();
    // Do something with random value
}

minstd_rand 是一个简单的线性同余引擎,类似于std::rand() 通常使用的引擎,但其状态封装在一个类中。如果您需要更高质量的伪随机序列,则可以使用其他引擎。如果您没有特定要求,Mersenne Twister std::mt19937 通常是一个不错的选择。

【讨论】:

  • @Brahim:保护什么?引擎是一个局部变量,所以只能被调用函数的线程访问。
  • 你是对的。我只是认为库函数的线程安全可能是未定义的。
【解决方案2】:

&lt;random&gt; 定义了许多您可以使用的 PRNG 类,它们不使用全局状态。

例如,使用默认的 Mersenne Twister,std::mt19937

#include <iostream>
#include <random>

int main() {
  int seed = 1234;
  std::mt19937 rng(seed);
  std::cout << "Random number: " << rng() << std::endl;
}

【讨论】:

    【解决方案3】:

    一种方法是使用自己的种子数据提供您自己的实现。 manpage for rand() 中提供了用于执行此操作的模板。

    static unsigned long next = 1;
    
    /* RAND_MAX assumed to be 32767 */
    int myrand(void) {
        next = next * 1103515245 + 12345;
        return((unsigned)(next/65536) % 32768);
    }
    
    void mysrand(unsigned seed) {
        next = seed;
    }
    

    【讨论】:

    • 他要求一个没有全局状态的解决方案,而你发布了一个全局状态的答案。
    • @DanielKO:实际上,他说他不想改变rand() 全局状态,但事实并非如此。然而,我明白你的意思,并且有点期待有人可以修改它以以适合他们目的的方式管理状态 - 例如,如果他们想要每个线程一个种子,这将需要未解决的自定义逻辑在任何答案中。
    • 注意:上面的代码是从手册页逐字复制的。这实际上只是一个示例,说明如何以非常便携的方式(以及使用自定义状态数据)生成可预测的随机数序列。如果您专门针对 C++11,使用 &lt;random&gt; 的方法可能会更好。所写的代码不是线程安全的。要实现线程安全,您需要以与您的线程安全策略相匹配的方式管理状态变量 next
    猜你喜欢
    • 2021-01-23
    • 2020-12-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-01
    • 1970-01-01
    相关资源
    最近更新 更多