我试图预先计算使用C ++ 11的随机值random
库在编译时。 我主要是下面的例子。 我在做什么错在这里?
using namespace std;
#include <iostream>
#include <vector>
#include <random>
vector<double> rands;
typedef std::mt19937_64 RNG;
uint64_t seed_val;
RNG rng;
void initialize() {
rng.seed(seed_val);
}
constexpr vector<double> generate_random( ) //size_t numbers)
{
int numbers = 1000;
std::uniform_real_distribution<double> zero_one(0.0, 1.0);
for (unsigned int i = 0; i < numbers; i++) {
double rand_num = zero_one(rng);
rands.push_back( rand_num );
}
return rands;
}
int main()
{
cout << "TMP rands";
for_each( rands.begin(), rands.end(), [] (double value)
{
cout<<value<<endl;
});
}
下面是无耻地窃取的例子编译时随机数发生器在这里 ,但认为它可能是谁看起来这件事的人有用:
template<u32 S, u32 A = 16807UL, u32 C = 0UL, u32 M = (1UL<<31)-1>
struct LinearGenerator {
static const u32 state = ((u64)S * A + C) % M;
static const u32 value = state;
typedef LinearGenerator<state> next;
struct Split { // Leapfrog
typedef LinearGenerator< state, A*A, 0, M> Gen1;
typedef LinearGenerator<next::state, A*A, 0, M> Gen2;
};
};
仅constexpr
功能和常量表达式可以在编译的时候进行评估。 这排除了<chrono>
和<random>
。
你可以做的是访问__TIME__
预处理器宏和定义自己的PRNG一行,组成constexpr
功能。
有关于这一主题的研究论文: 随机数发生器,用于C ++模板元程序包含的代码段为__TIME__
伎俩。 它还谈到支持不同的随机数字引擎和分布正交选择。
我会尝试从外部拉动它。 一个很简单的例子是在编译命令定义的宏变量编译程序。 这里$RANDOM
是一个特殊的内置在UNIX / Linux系统,可自动返回一个随机的16位数字的变量。
g++ -D__RANDOM__=$RANDOM yourprog.cpp -o yourprog
//yourprog.cpp
#include <iostream>
int main() {
std::cout << "Random variable " << __RANDOM__ << std::endl;
return 0;
}
您也可以编写自己的脚本或可执行文件分配给您的宏变量。
//DevRandomGenerator.cpp
#include <iostream>
#include <fstream>
class DevRandom {
private:
std::ifstream stream;
public:
DevRandom() {
stream.open("/dev/urandom",std::ios::in|std::ios::binary);
}
unsigned int unsignedInt() {
unsigned int u = 0;
stream.read((char*)&u, sizeof(unsigned int));
return u;
}
};
int main() {
DevRandom rand;
std::cout << rand.unsignedInt() << std::endl;
return 0;
}
然后编译如下:
g++ DevRandomGenerator.cpp -o DevRandomGenerator
g++ -D__RANDOM__="$(./DevRandomGenerator)" yourprog.cpp -o yourprog
一个更好的随机数发生器将编写使用音频和视频输入的程序。
不仅是system_clock::now()
无法编译时可知的,但你的函数被标记为返回一个布尔值,但没有return语句的任何地方。
我知道这个问题是五岁了,并且已经有一个公认的答案。 即便如此,我想补充一点,那当然是可能在编译时生成随机数,与你会得到随机数的每次运行程序时的顺序相同的理解。 简单地说,如果种子在编译时已知,则编译器允许找出随机数将被输出,并且只需打开程序分为“输出数的序列。”
编译器会限制他们优化的积极程度,所以我不能保证他们会永远让这种替代,我怀疑任何编译器将能够做出的东西一样复杂梅森难题替代,但更简单的东西像linear_congruential_engine
有机会(也只有这样,才能确保它的发生是有编译器输出的汇编代码,然后看看你的汇编代码)。
我知道这是可能的,因为我实现了建模的随机生成random_device
所用马尔萨利亚的Xorshift算法 。 由于马尔萨利亚的纸张实际上包括多个相关算法,我有类采取模板参数选择要使用的换档模式。 我想知道如果编译器将优化了switch
我使用的语句。 忘了通过一个种子,所以编译器所使用的缺省,即,种子在编译时已知。 当我看着汇编代码,不仅是switch
了,但GCC了优化后的程序分为“输出这三个数字。”
在这个问题中列出的程序的最终版本实际上从未调用的函数生成的数字序列,从不调用的函数种子发生器。 这个版本将做到这一点,但我怀疑它会变成“打印随机数的序列。”
#include <algorithm>
#include <cstdlib>
#include <iostream>
#include <iterator>
#include <random>
int get_seed()
{
int hour = std::atoi(__TIME__);
int min = std::atoi(__TIME__ + 3);
int sec = std::atoi(__TIME__ + 6);
return 10000 * hour + 100 * min + sec;
}
int main()
{
// get_seed() returns an int based on __TIME__ (a string literal
// set by the preprocessor), which is known at compile time.
//
// Also, w/r/t the engines in <random>: not setting a seed explicitly
// will use a default seed, which is known at compile time. So if
// you're OK getting the same sequence of numbers for any compilation,
// then "std::mt19937_64 rng;" may be all you need.
std::mt19937_64 rng(get_seed());
std::uniform_real_distribution<double> zero_one(0.0, 1.0);
const int COUNT = 1000;
std::generate_n(std::ostream_iterator<double>(std::cout, "\n"), COUNT,
[&rng, &zero_one]() { return zero_one(rng); });
return 0;
}
按照该错误消息:
cpp11tmprands.cpp:22:15: error: ‘rands’ was not declared in this scope
变量rands
不在的范围内声明main
。 使它成为一个全局变量,而不是当地的generate_random
和错误会自行消失。