用于skipList的C ++中的随机数生成器

时间:2018-04-30 20:31:57

标签: c++

我想要一个随机数生成器用于跳过列表实现并获得以下逻辑。 我可以解释一下如何生成随机数。 我看到使用bit wise运算符但无法理解逻辑。

#include <stdint.h>
#include <iostream>
using namespace std;
typedef unsigned int          uint32_t;
typedef unsigned long long    uint64_t;

class Random {
 private:
  uint32_t seed_;
 public:
  explicit Random(uint32_t s) : seed_(s & 0x7fffffffu) {
    // Avoid bad seeds.
    if (seed_ == 0 || seed_ == 2147483647L) {
      seed_ = 1;
    }
  }
  uint32_t Next() {
    static const uint32_t M = 2147483647L;   // 2^31-1
    static const uint64_t A = 16807;  // bits 14, 8, 7, 5, 2, 1, 0
    uint64_t product = seed_ * A;

    seed_ = static_cast<uint32_t>((product >> 31) + (product & M));

    if (seed_ > M) {
      seed_ -= M;
    }
    return seed_;
  }

};



int main()
{
    Random rnd_(0xdeadbeef);
    int i = 10;
    while(i)
    {

        cout << rnd_.Next() << "\n";
        i--;
    }
    return 0;
}

1 个答案:

答案 0 :(得分:0)

<强> TL;博士

需要一个长数字(最多64位(二进制等效小数位)),分成两个32位长数,并将前半部分加到第二个。十进制等值将是如果起始数字是12345并且我们想要将它除以4 th 小数空间,我们将数字拆分为1和2345,并添加两个,产生2346。

唯一的工作似乎就在这里:

 seed_ = static_cast<uint32_t>((product >> 31) + (product & M));

这样做是右移(除以2 31 )乘积并添加M的第一个字节。

所以如果种子是1957983907,那么产品是(16807 * 1957983907 = 32907835524949),即111011110110111110011110110001100011101010101(这是一个64位的数字,可以分成两个(32位长)部分

00000000000000000001110111101101
11110011110110001100011101010101

),左移31它会给你11101111011011(以上数字的“顶部”两个字节。)

然后,你做(产品&amp; M),给出以下(产品在顶部,M在底部):

00000000000000000001110111101101 11110011110110001100011101010101
00000000000000000000000000000000 11111111111111111111111111111111

它通过两个数字,一点一点地对每个进行add,得到M的后半部分(11110011110110001100011101010101),等于4091070293.

然后它添加了两个,确保它适合32位长的数字,如果没有则包装它。