【发布时间】:2012-12-10 04:25:57
【问题描述】:
我需要生成随机数,但范围尽可能广(至少 64 位)。我不在乎分布是否完美,所以std::rand() 会起作用,但它只返回int。我知道 c++11 具有一些随机数生成能力,可以给出任何大小的数字,但使用起来非常复杂。有人可以发布一个简单示例,说明如何尽可能简单地使用它以尽可能简单的方式(如std::rand())获得所描述的功能(64 位或更多随机数)?
【问题讨论】:
我需要生成随机数,但范围尽可能广(至少 64 位)。我不在乎分布是否完美,所以std::rand() 会起作用,但它只返回int。我知道 c++11 具有一些随机数生成能力,可以给出任何大小的数字,但使用起来非常复杂。有人可以发布一个简单示例,说明如何尽可能简单地使用它以尽可能简单的方式(如std::rand())获得所描述的功能(64 位或更多随机数)?
【问题讨论】:
不是 C++11,但足够简单
((unsigned long long)rand() << 32) + rand()这里我们生成int64的两部分作为int32的
正如JasonD 所指出的,它假定rand() 生成32 位整数。可以异或
rand() << x、rand() << (2*x)、rand() << (3*x) 等,其中x rand() 数字生成。应该也可以的。
【讨论】:
RAND_MAX 来确定这一点。
RAND_MAX 为 0x7FFF,即 15 位。
我们可以轻松地将随机数生成器引擎封装到类似 srand/rand 的方法中,如下所示:
#include <random>
#include <iostream>
struct MT19937 {
private:
static std::mt19937_64 rng;
public:
// This is equivalent to srand().
static void seed(uint64_t new_seed = std::mt19937_64::default_seed) {
rng.seed(new_seed);
}
// This is equivalent to rand().
static uint64_t get() {
return rng();
}
};
std::mt19937_64 MT19937::rng;
int main() {
MT19937::seed(/*put your seed here*/);
for (int i = 0; i < 10; ++ i)
std::cout << MT19937::get() << std::endl;
}
(与srand 和rand 一样,此实现不关心线程安全。)
包装函数非常简单,您可以直接使用引擎。
#include <random>
#include <iostream>
static std::mt19937_64 rng;
int main() {
rng.seed(/*put your seed here*/);
for (int i = 0; i < 10; ++ i)
std::cout << rng() << std::endl;
}
【讨论】:
std::mt19937_64::default_seed 被标准化为 5489u,因此您的示例程序将始终产生相同的输出序列。
srand() 中一样,您需要提供自己的种子才能获得不同的随机序列。
这是为此目的使用 C++11 随机数生成的方法(调整自 http://en.cppreference.com/w/cpp/numeric/random/uniform_int_distribution):
#include <random>
#include <iostream>
int main()
{
/* Initialise. Do this once (not for every
random number). */
std::random_device rd;
std::mt19937_64 gen(rd());
/* This is where you define the number generator for unsigned long long: */
std::uniform_int_distribution<unsigned long long> dis;
/* A few random numbers: */
for (int n=0; n<10; ++n)
std::cout << dis(gen) << ' ';
std::cout << std::endl;
return 0;
}
您可以使用cstdint 中的std::uintmax_t 来代替unsigned long long,以获得最大可能的整数范围(不使用实际的大整数库)。
【讨论】:
sizeof(unsigned) 字节的熵。如果您需要更多,可以将std::seed_seq 传递给mt19937 的构造函数,以便传递任意数量的随机字节。