如果此处的准确性是一个问题,您可以通过随机化有效位来创建具有更精细分级的随机数。
假设我们想要一个介于 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);
}
注意:我不知道所有平台上 unsigned long long(64 位)的位数是否大于双尾数位数(IEE 754 为 53 位)。
如果不是这种情况,包含if (sizeof(unsigned long long)*8 > num_mant_bits) ... 之类的检查可能是“聪明的”。