如果这里存在精度问题,则可以通过对有效位进行随机化来创建具有更好刻度的随机数。假设我们希望在0.0和1000.0之间有一个两倍。
在MSVC(12 / Win32)上,RAND_MAX是32767。
如果使用通用rand()/RAND_MAX
方案,您的差距将达到
1.0 / 32767.0 * ( 1000.0 - 0.0) = 0.0305 ...
如果是IEE 754双变量(53个有效位)和53位随机化,则0到1000问题的最小可能随机间隙为
2^-53 * (1000.0 - 0.0) = 1.110e-13
因此大大降低。
缺点是需要4个rand()调用才能获得随机整数(假设为15位RNG)。
double random_range (double const range_min, double const range_max)
{
static unsigned long long const mant_mask53(9007199254740991);
static double const i_to_d53(1.0/9007199254740992.0);
unsigned long long const r( (unsigned long long(rand()) | (unsigned long long(rand()) << 15) | (unsigned long long(rand()) << 30) | (unsigned long long(rand()) << 45)) & mant_mask53 );
return range_min + i_to_d53*double(r)*(range_max-range_min);
}
如果尾数或RNG的位数未知,则需要在函数中获得相应的值。
#include <limits>
using namespace std;
double random_range_p (double const range_min, double const range_max)
{
static unsigned long long const num_mant_bits(numeric_limits<double>::digits), ll_one(1),
mant_limit(ll_one << num_mant_bits);
static double const i_to_d(1.0/double(mant_limit));
static size_t num_rand_calls, rng_bits;
if (num_rand_calls == 0 || rng_bits == 0)
{
size_t const rand_max(RAND_MAX), one(1);
while (rand_max > (one << rng_bits))
{
++rng_bits;
}
num_rand_calls = size_t(ceil(double(num_mant_bits)/double(rng_bits)));
}
unsigned long long r(0);
for (size_t i=0; i<num_rand_calls; ++i)
{
r |= (unsigned long long(rand()) << (i*rng_bits));
}
r = r & (mant_limit-ll_one);
return range_min + i_to_d*double(r)*(range_max-range_min);
}
注意:我不知道在所有平台上无符号long long(64位)的位数是否大于双尾数位数(IEE 754的53位)。if (sizeof(unsigned long long)*8 > num_mant_bits) ...
如果不是这样的话,包括支票可能是“聪明的” 。