我有以下功能:
typedef unsigned long long int UINT64;
UINT64 getRandom(const UINT64 &begin = 0, const UINT64 &end = 100) {
return begin >= end ? 0 : begin + (UINT64) ((end - begin)*rand()/(double)RAND_MAX);
};
Run Code Online (Sandbox Code Playgroud)
每当我打电话
getRandom(0, ULLONG_MAX);
Run Code Online (Sandbox Code Playgroud)
要么
getRandom(0, LLONG_MAX);
Run Code Online (Sandbox Code Playgroud)
我总是得到相同的价值562967133814800.我该如何解决这个问题?
Ric*_*ard 17
什么是rand()?
根据此的rand()函数返回范围内的值[0,RAND_MAX].
什么是RAND_MAX?
根据这个,RAND_MAX是"一个整数常量表达式,其值是rand函数返回的最大值.该值与库有关,但在任何标准库实现上保证至少为32767."
精确是一个问题
您可以使用rand()/(double)RAND_MAX,但您可能只有32767个离散值.因此,虽然你的数字很大,但实际上并没有更多的数字.这可能是一个问题.
播种可能是一个问题
另外,您不会谈论如何调用该函数.你是否运行该程序一次LLONG_MAX,另一次用ULLONG_MAX?在这种情况下,您看到的行为是因为您每次都隐式使用相同的随机种子.换句话说,每次运行程序时,它都会生成完全相同的随机数序列.
我该如何种子?
你可以使用这样的srand()功能:
#include <stdlib.h> /* srand, rand */
#include <time.h> /* time */
int main (){
srand (time(NULL));
//The rest of your program goes here
}
Run Code Online (Sandbox Code Playgroud)
现在,每次运行程序时,您都会得到一个新的随机数序列.
溢出是一个问题
考虑这部分((end - begin)*rand()/(double)RAND_MAX).
什么是(end-begin)?根据定义,它是LLONG_MAX或者ULLONG_MAX这些数据类型可以容纳的最大可能值.因此,将它们乘以任何东西都是不好的.但你做到了!你将它们乘以rand(),这是非零.这会导致溢出.但我们可以解决这个问题......
运营秩序是一个问题
然后你将它们除以RAND_MAX.我认为你的操作顺序错了.你真的想说:
((end - begin) * (rand()/(double)RAND_MAX) )
Run Code Online (Sandbox Code Playgroud)
注意新的parantheses!(rand()/(double)RAND_MAX)
现在您将整数乘以一个分数,因此您可以保证不会溢出.但这引入了一个新问题......
促销是一个问题
但是还有一个更深层次的问题.你将int除以double.当你做的int是提升到一个double.双精度是一个浮点数,这基本上意味着它牺牲精度以获得大范围.那可能就是在咬你.当你获得越来越大的数字时,你ullong和你的llong最终都会被投射到相同的值.如果您首先溢出数据类型(见上文),则尤其如此.
哦,哦
所以,基本上,你提出的关于PRNG的一切都是错误的.
也许这就是John von Neumann所说的原因
任何试图通过确定性手段产生随机数的人当然都处于犯罪状态.
而且,有时,我们为这些罪行买单.
我怎么能自己解脱?
C++ 11提供了一些不错的功能.您可以按如下方式使用它
#include <iostream>
#include <random>
#include <limits>
int main(){
std::random_device rd; //Get a random seed from the OS entropy device, or whatever
std::mt19937_64 eng(rd()); //Use the 64-bit Mersenne Twister 19937 generator
//and seed it with entropy.
//Define the distribution, by default it goes from 0 to MAX(unsigned long long)
//or what have you.
std::uniform_int_distribution<unsigned long long> distr;
//Generate random numbers
for(int n=0; n<40; n++)
std::cout << distr(eng) << ' ';
std::cout << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
(请注意,适当播种发电机很困难.这个问题可以解决这个问题.)