根据标准mt19937::default_seed,的值为5489u:
static constexpr result_type default_seed = 5489u;
Run Code Online (Sandbox Code Playgroud)
这看起来很人为。
这背后有什么(数学或理论)原因吗?
我遇到的问题发生在我试图测试生成伪随机数的cppreference示例时.举个例子:
#include <iostream>
#include <random>
int main() {
std::random_device rd{};
std::mt19937 gen{rd()};
std::uniform_int_distribution<> dis{1, 6};
for(int n = 0; n < 10; ++n) {
std::cout << dis(gen) << ' ';
}
std::cout << '\n';
}
Run Code Online (Sandbox Code Playgroud)
在我的机器上,它会导致崩溃.通过"崩溃"我的意思是该过程只是挂起并0xC0000005在几秒钟后返回.
我想知道是什么原因造成的.GCC错误?我的机器出现故障?我决定测试,结果非常令人惊讶.例如,给出以下略微修改的示例:
#include <iostream>
#include <random>
int main() {
std::random_device rd{};
std::mt19937_64 gen{rd()}; // notice the _64 here
std::uniform_int_distribution<> dis{1, 6};
for(int n = 0; n < 10; ++n) {
std::cout << dis(gen) << ' ';
}
std::cout << '\n';
} …Run Code Online (Sandbox Code Playgroud) <random>C++中有确定性随机数生成器吗?
有问题的一点是我的 Windows 机器上的以下代码:
#include<iostream>
#include<random>
int main(){
std::mt19937 g;
std::normal_distribution<double> d;
for(int i=0;i<100;++i){
g.seed(65472381);
std::cout << "List[65472381] = " << d(g) << "\n";
}
}
Run Code Online (Sandbox Code Playgroud)
产生以下结果:
List[65472381]=0.972683
List[65472381]=-0.773812
List[65472381]=0.972683
List[65472381]=-0.773812
List[65472381]=0.972683
List[65472381]=-0.773812
...
Run Code Online (Sandbox Code Playgroud)
我的困惑在于,尽管使用了之前每次0.972683 != -0.773812重置的种子。65472381g
我的处理器是Zen 2,操作系统是 Windows 10 Pro,版本 22H2。编译器是GCC(x86_64-w64-mingw32/12.2.0)。但通过在不同的虚拟机和编译器上在线测试代码,结果似乎在您的计算机上也可能是相同的。
我真正寻求的是一种从任意固定通用列表中获取第 i 个数字的方法,该通用列表长度为 4,294,967,295,随机分布的数字在 SPACETIME O(1) 中,这意味着该列表中没有任何元素被存储。
#include <random>
std::random_device rd; // only used once to initialise (seed) engine
std::mt19937 rng(rd()); // random-number engine used (Mersenne-Twister in this case)
std::uniform_int_distribution<int> uni(min,max); // guaranteed unbiased
auto random_integer = uni(rng);
Run Code Online (Sandbox Code Playgroud)
我也愿意使用该rand()方法srand(time(NULL))。
这些方法的成本有多高?一个比另一个快很多吗?
之前(stackoverflow)已经问过这个问题,但(接受的)答案并不令人满意。
以下示例保存并加载状态,但取决于生成的值的数量,它是否起作用:
#include <fstream>
#include <iostream>
#include <random>
#include <cassert>
int main()
{
const int preN = 4;
const int middleN = 0;
// initialize randGen
std::mt19937 randGen1;
std::normal_distribution<double> distribution1;
// print some initial random numbers
for (int i=0;i<preN;++i)
std::cout << distribution1(randGen1)<<" ";
// save state
std::cout << std::endl << "Saving...\n";
{
std::ofstream fout("seed.dat");
fout << randGen1;
}
// maybe advance randGen1
for (int i=0;i<middleN;++i)
std::cout << distribution1(randGen1)<<" ";
// load saved state into randGen2
std::cout << std::endl …Run Code Online (Sandbox Code Playgroud) 我有一个函数,它使用类型为 的静态函数变量rand_double()生成随机浮点值。多个线程可以同时使用该函数。std::mt19937
#include <random>
auto random_double(double min, double max) {
static std::mt19937 generator{std::random_device{}()}; // Forgot to seed it, thanks @user4581301
return std::uniform_real_distribution<>{min, max}(generator);
}
Run Code Online (Sandbox Code Playgroud)
我的第一个问题是,上面的代码是线程安全的吗?我知道从C++11开始,静态函数变量的初始化始终是线程安全的,但是并发使用生成器怎么样?
我见过std::mt19937以下几种用法:
#include <random>
size_t get_rand()
{
static thread_local std::mt19937 generator(time(0));
std::uniform_int_distribution<int> distribution(0, 10);
return distribution(generator);
}
Run Code Online (Sandbox Code Playgroud)
我想知道使用static thread_local而不是static在这里能带来什么好处。// 第一个static是多余的
据我所知,在第二种情况下,generator线程的生命周期结束之前。是否有其他共同点或特殊情况的好处/差异?
在程序中,经常在不同的类中生成随机数。因此,我想创建一个返回生成器std :: mt19937的单个实例的类。我还考虑到某些编译器不能与std :: random_device一起使用(为此,请检查熵的值)。我创建了一个类单例。
#include <iostream>
#include <random>
#include <chrono>
class RandomGenerator
{
public:
static RandomGenerator& Instance() {
static RandomGenerator s;
return s;
}
std::mt19937 get();
private:
RandomGenerator();
~RandomGenerator() {}
RandomGenerator(RandomGenerator const&) = delete;
RandomGenerator& operator= (RandomGenerator const&) = delete;
std::mt19937 mt;
};
RandomGenerator::RandomGenerator() {
std::random_device rd;
if (rd.entropy() != 0) {
mt.seed(rd());
}
else {
auto seed = std::chrono::high_resolution_clock::now().time_since_epoch().count();
mt.seed(seed);
}
}
std::mt19937 RandomGenerator::get() {
return mt;
}
int main() {
std::mt19937 &mt = RandomGenerator::Instance().get();
std::uniform_real_distribution<double> dist(0.0, 1.0); …Run Code Online (Sandbox Code Playgroud) #include <iostream>
#include <random>
int gen_ran(void)
{
static std::random_device rd;
static std::mt19937 gen(rd());
static std::uniform_int_distribution<int> dist(0, 9);
return dist(gen);
}
int main()
{
for (int i = 0; i < 50; i++)
{
std::cout << gen_ran() << " ";
if ((i + 1) % 10 == 0)
std::cout << std::endl;
}
}
Run Code Online (Sandbox Code Playgroud)
我不太明白为什么我们可以在 gen_ran() 函数的三行中的每一行中放置一个 static 。我用谷歌搜索了很多,但似乎没有明确的答案。
我的理解是,通过使用静态,我们只初始化对象一次,但每个类中的算法(random_device、mt19937、uniform_int_distribution)仍然可以生成随机数。那么static在函数被多次调用的时候可以节省一些计算机资源吗?
如果我不使用任何静态或在代码中使用一两个静态怎么样?如果我在每种情况下都不这么做,会有什么区别吗?非常感谢。
是否由标准保证如果std::mt19937用相同的数字播种,它将在所有平台上产生相同的数字序列?
换句话说,它的实现是由标准定义好还是std::rand()被认为是实现细节?
c++ ×10
mt19937 ×10
random ×7
c++11 ×4
static ×2
c++17 ×1
c++20 ×1
gcc ×1
optimization ×1
performance ×1
random-seed ×1
std ×1
thread-local ×1