我的当前代码存在一个特殊问题。我正在编写一个程序,需要从两个分布(正态分布和一个真实分布)生成随机实数。生成这些值的代码存在于for循环中:
char* buffer = new char[config.number_of_value * config.sizeof_line()];
//...
//Loop over how much values we want
for(std::size_t i = 0; i < config.number_of_value; ++i)
{
//Calculates the offset where the current line begins (0, sizeof_line * 1, sizeof_line * 2, etc.)
std::size_t line_offset = config.sizeof_line() * i;
//The actual numbers we want to output to the file
double x = next_uniform_real();
double y = config.y_intercept + config.slope * x + next_normal_real();
//Res is the number of character written. The character at buffer[res] is '\0', so we need
//To get rid of it
int res = sprintf((buffer + line_offset), "%f", x);
buffer[line_offset + res] = '0';
//Since we written double_rep_size character, we put the delimiter at double_rep_size index
res = sprintf((buffer + line_offset + config.data_point_character_size() + sizeof(char)), "%f", y);
buffer[line_offset + config.data_point_character_size() + sizeof(char) + res] = '0';
}
return buffer;
运行程序时,“number_of_value”的通常值为100'000。所以应该有10'000次调用next_uniform_real()和100'000调用next_normal_real()。奇怪的是,当我在Visual Studio 2017上用VSPerf配置这个代码时,我得到了对mersenne_twister生成器的227'242个调用,这是对每个函数的113'621调用。正如你所看到的那样,有超过3'621个电话。
任何人都可以帮我解决这个问题吗?
供参考,功能如下:
double generator::next_uniform_real()
{
return uniform_real_dist(eng);
}
double generator::next_normal_real()
{
return normal_dist(eng);
}
其中eng是std :: mt19937,当random_device没有熵时,使用random_device或time(0)播种。 normal_dist的类型为std :: normal_real_distribution&lt;&gt; 和uniform_real_dist的类型为std :: uniform_real_distribution&lt;&gt;
对于那些想知道的人,我正在填充一个char *缓冲区,这样我就可以对一个ostream进行一次写操作,而不是每次迭代循环一次。
(顺便说一句,如果有人知道更快的方式将float / double值写入char *或者生成实数的方法比这种方法更快,那真的很有帮助!)
答案 0 :(得分:6)
std::normal_distribution
的所有主要标准库实现都使用Marsaglia polar method。如维基百科文章中所述,
此程序需要对基础随机数生成器进行大约27%的评估(仅生成点的π/4≈79%位于单位圆内)。
您的号码听起来是正确的(每个号码1个RNG呼叫100000个统一实数加上每个号码1.27个RNG呼叫的100000个正常实数为227000)。
答案 1 :(得分:4)
想象一下,如果您尝试生成1到10之间的随机整数,并且您的输入源提供1到12之间的随机数(包括1和12)。如果你得到1到10之间的数字,你可以输出它。但是如果得到11,你必须得到1到12之间的另一个数字。因此,当将随机源与具有不同分布的随机输出匹配时,可能需要额外的调用。