生成随机64位整数

时间:2011-11-14 10:15:57

标签: c++ random 64-bit

我需要你的帮助,请给我一些建议。从编程珍珠我知道要生成随机30位整数,我们应该这样写:

RAND_MAX*rand()+rand()

但是,我可以做什么来生成不是30,而是64位随机整数呢?我认为这是非常低效的方法,如果我乘以两个30位整数然后再乘以4位整数,那么我应该使用什么样的方法? 我现在使用popcount_1不同的64位方法,我想在随机整数上测试它(我也在测量每个完成任务所需的时间)

6 个答案:

答案 0 :(得分:7)

首先,我怀疑你发布的30位解决方案 整数。 RAND_MAX本身可能是31位值,RAND_MAX * rand() + rand()可能会溢出,从而产生未定义的行为 (在实践中,负值)。

如果您需要的值大于RAND_MAX的保证最低值,或者 就此而言,任何不小于的东西 RAND_MAX,唯一的解决方案是使用连续调用 rand(),并结合这些值,但您需要仔细执行此操作,并且 验证结果。 (rand()的大多数实现都使用线性 一致的发电机,虽然适合某些任务,但却不适用 在这种情况下特别好。)无论如何,像:

unsigned 
rand256()
{
    static unsigned const limit = RAND_MAX - RAND_MAX % 256;
    unsigned result = rand();
    while ( result >= limit ) {
        result = rand();
    }
    return result % 256;
}

unsigned long long
rand64bits()
{
    unsigned long long results = 0ULL;
    for ( int count = 8; count > 0; -- count ) {
        results = 256U * results + rand256();
    }
    return results;
}

rand256中的代码旨在消除其他情况 将RAND_MAX值映射到256个值时不可避免的偏差。)

答案 1 :(得分:3)

如果boost是一个选项,您可以使用boost random

答案 2 :(得分:3)

这可能是一个解决方案,没有乘法:

r30 = RAND_MAX*rand()+rand()
s30 = RAND_MAX*rand()+rand()
t4  = rand() & 0xf

res = (r30 << 34) + (s30 << 4) + t4

答案 3 :(得分:2)

随机64位int基本上是64个随机位,被解释为int。

使用随机字节(see here for how)填充长度为8的字节数组,并将其解释为int(see here for how)。

答案 4 :(得分:1)

通用解决方案:

template <unsigned long long I> struct log2 {
  static const int result = 1 + log2<I/2>::result;
};
template <> struct log2<1> {
  static const int result = 0;
};

template <typename UINT> UINT genrand() {
  UINT result = 0;
  int bits = std::numeric_limits<UINT>::digits;
  int rand_bits = log2<RAND_MAX>::result;
  while (bits > 0) {
    int r = rand();
    while (r >= (1<<rand_bits)) r = rand(); // Retry if too big.
    result <<= rand_bits;
    result += r;
    bits -= rand_bits;
  }
  return result;
}

使用:unsigned long long R = genrand<unsigned long long>();

bits计数器会跟踪仍然需要的位数。

答案 5 :(得分:0)

'返回0到RAND_MAX(包括0和RAND_MAX)之间的伪随机整数值。 - http://en.cppreference.com/w/cpp/numeric/random/rand

所以你应该使用RAND_MAX + 1(就像数字生成一个数字,然后将其转换为基数10)而不是RAND_MAX。 通过这种方式,您可以生成基数为RAND_MAX + 1(可能带有前导零)的一位,两位,三位等数字,并将它们转换为基数10并获得任意大数。

您获得的大于所需MAX_VALUE的所有内容都可以被丢弃,您仍然可以获得每个数字的1 /(MAX_VALUE + 1)概率。

请注意,此方法可能需要一段时间,特别是如果您所需的MAX_VALUE比丢弃不需要的数字之前可以获得的最大值小很多,作为获得随机数的预期步数在[0,MAX_VALUE]中使用此算法的是:(MAX_OBTAINABLE_VALUE + 1)/(MAX_VALUE + 1)