[英]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.