相关疑难解决方法(0)

如何简洁,便携,彻底地播种mt19937 PRNG?

我似乎看到很多答案,有人建议使用它<random>来生成随机数,通常伴随着这样的代码:

std::random_device rd;  
std::mt19937 gen(rd());
std::uniform_int_distribution<> dis(0, 5);
dis(gen);
Run Code Online (Sandbox Code Playgroud)

通常这会取代某种"邪恶的憎恶",例如:

srand(time(NULL));
rand()%6;
Run Code Online (Sandbox Code Playgroud)

我们可能会批评旧的方式,认为time(NULL)提供低熵,time(NULL)可预测,最终结果是不均匀的.

但所有这一切都适用于新的方式:它只有一个更光亮的贴面.

  • rd()返回一个unsigned int.这至少有16位,可能是32位.这还不足以为MT的19937位状态提供种子.

  • 使用std::mt19937 gen(rd());gen()(以32位播种并查看第一个输出)不能提供良好的输出分布.7和13永远不会是第一个输出.两粒种子产生0.十二粒种子产生1226181350.(链接)

  • std::random_device可以(有时是)实现为具有固定种子的简单PRNG.因此,它可能在每次运行时产生相同的序列.(链接)这甚至比time(NULL).

更糟糕的是,尽管存在它们包含的问题,但复制和粘贴上述代码片段非常容易.对此的一些解决方案需要获得可能不适合每个人的大型 .

鉴于此,我的问题是如何在C++中简洁,便携,彻底地播种mt19937 PRNG?

鉴于上述问题,一个很好的答案:

  • 必须完全播种mt19937/mt19937_64.
  • 不能单独依赖std::random_devicetime(NULL)作为熵的来源.
  • 不应该依赖Boost或其他图书馆.
  • 应该适合少量的线条,这样看起来很好,可以复制粘贴到答案中.

思考

  • 我目前的想法是,输出来自std::random_device(可能通过XOR)time(NULL),从地址空间随机化得到的值,以及硬编码常量(可以在分配期间设置)以获得熵的最佳努力.

  • std::random_device::entropy() 没有很好地说明std::random_device可能做什么或不做什么.

c++ random c++11

106
推荐指数
4
解决办法
7189
查看次数

为C++类播种rand()

我正在开发一个rand()在构造函数中使用a的C++类.我真的希望这个班级能够在各方面照顾好自己,但我不确定在哪里播种rand().

如果我rand()在构造函数中播种,那么每次构造我的对象类型的新实例时它都将被播种.因此,如果我按顺序创建3个对象,它们将在同一秒内创建,因此具有相同的种子rand(),为对象的3个实例中的每个实例生成完全相同的数据.

我想rand()在类代码中播种,而不是在创建对象之前必须在我的程序的main函数中进行.我想做一个static bool seeded;表示是否rand()已播种的变量,但我不确定如何在创建类时将其初始化为false.

我的想法是这样的

myConstructor(){
    if(!seeded){
        srand(time(NULL));
        seeded = true;
    }

    myVariable = rand()%maxVal;
}
Run Code Online (Sandbox Code Playgroud)

我想如果我能弄清楚如何在程序开始时将静态值初始化为false,那么这将有效.我的理解是,如果对象的所有实例都是静态的,那么将此静态值更改为true将会传递该对象的所有实例,因此只会在第一次创建对象类型时执行种子函数.

c++ random class static-variables random-seed

6
推荐指数
2
解决办法
6826
查看次数

在 random_device 和 seed_seq 之间决定以生成多个随机数序列的种子

在编写需要多个独立的随机数分布/序列(下面的示例中有两个)的代码时,似乎有两种典型的方法来实现(伪)随机数生成。一种是简单地使用一个random_device对象为两个独立引擎生成两个随机种子:

std::random_device rd;
std::mt19937 en(rd());
std::mt19937 en2(rd());
std::uniform_real_distribution<> ureald{min,max};
std::uniform_int_distribution<> uintd{min,max};
Run Code Online (Sandbox Code Playgroud)

另一个涉及使用random_device对象来创建seed_seq使用多个随机“源”的对象:

// NOTE: keeping this here for history, but a (hopefully) corrected version of
// this implementation is posted below the edit
std::random_device rd;
std::seed_seq seedseq{rd(), rd(), rd()}; // is there an optimal number of rd() to use?
std::vector<uint32_t> seeds(5);
seedseq.generate(seeds.begin(), seeds.end());
std::mt19937 en3(seeds[0]);
std::mt19937 en4(seeds[1]);
std::uniform_real_distribution<> ureald{min,max};
std::uniform_int_distribution<> uintd{min,max};
Run Code Online (Sandbox Code Playgroud)

在这两个中,是否有首选方法?为什么?如果是后者,random_device在生成seed_seq对象时是否有最佳数量的“源” ?

是否有比我上面概述的这两个实现中的任何一个更好的随机数生成方法?

谢谢!


编辑

(希望)修正seed_seq多个发行版的实现版本:

std::random_device …
Run Code Online (Sandbox Code Playgroud)

c++ random c++11

2
推荐指数
1
解决办法
1268
查看次数

C++ 随机数每次都相同的序列

我写这个是为了生成一个随机密码:

#include <iostream>
#include <fstream>
#include <string>
#include <cstdlib>
using namespace std;

string read(string value) { //read value
    ifstream input;
    int olength;
    string line = "", output = "";
    size_t pos;
    bool a = true;
    int i = 0;
    input.open("pg_options.txt");
    if (!input.is_open()) {
        cout << "pg_options.txt missing.";
        return "error";
    }
    while (getline(input, line)) {
        pos = line.find(value);
        if (pos != string::npos) {
            while (a == true) {
                if (line[i] == '=') {
                    i++;
                    break;
                }
                else {
                    i++;
                }
            } …
Run Code Online (Sandbox Code Playgroud)

c++ random

2
推荐指数
1
解决办法
66
查看次数

标签 统计

c++ ×4

random ×4

c++11 ×2

class ×1

random-seed ×1

static-variables ×1