繁体   English   中英

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

[英]Random Number Generator in C++ for skipList

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

#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;
}

tl; dr

它需要一个长数字(最大为64位(十进制的二进制等效项)),分为两个32位长的数字,然后将前半部分与后半部分相加。 相应的十进制数是如果起始号码是12345,我们希望通过4 十进制空间分割它,我们就数分成1和2345,并添加了两下,生产2346。


唯一的工作似乎在这里:

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

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

因此,如果种子为1957983907,则乘积为(16807 * 1957983907 = 32907835524949),即111011110110111111110011110110001100011101010101(64位数字,可以分解为两个(32位长)部分)

00000000000000000001110111101101
11110011110110001100011101010101

),将其左移31会得到11101111011011(上述数字的“顶部”两个字节。)

然后,您执行(产品&M),并给出以下内容(顶部为产品,底部为M):

00000000000000000001110111101101 11110011110110001100011101010101
00000000000000000000000000000000 11111111111111111111111111111111

它通过两个数字,逐位,做一个add在每个,它获取M(11110011110110001100011101010101),其等于4091070293的第二个一半。

然后,将两者相加,确保它适合32位长的数字,如果没有,则将其包装。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM