这里有一个简单的LCG,我制作它是为了更多地了解伪随机数的生成。
这个实现正确吗?如果是的话,我如何进一步改进它?
下面的代码是自包含的,应该没有问题地运行。
#include <chrono>
#include <iostream>
#include <map>
namespace Random {
class LCG {
static constexpr uint64_t const A = 0x5851F42D4C957F2D;
static constexpr uint64_t const C = 0x14057B7EF767814F;
static constexpr uint64_t const M = 0xFFFFFFFFFFFFFFFF;
uint64_t this_seed;
auto now() noexcept {
using namespace std::chrono;
auto const output = high_resolution_clock::now();
return output.time_since_epoch().count();
}
public:
LCG() noexcept
: this_seed(now()) {
}
LCG(uint64_t const value) noexcept
: this_seed(value) {
}
void seed() noexcept {
this_seed = now();
}
void seed(uint64_t const value) noexcept {
this_seed = value;
}
// [0, 2 ^ 64 - 1)
auto next() noexcept {
this_seed = (this_seed * A + C) & M;
return this_seed;
}
void discard(uint64_t const amount) noexcept {
for (uint64_t i = 0; i != amount; ++i) {
next();
}
}
// [0, 1)
double get() noexcept {
return static_cast<double>(next()) / M;
}
// x - 0 == (-1 | 0 | 1) ? 0 : x > 0 ? [0, x) : (x, 0]
int64_t get(int64_t const x) noexcept {
return static_cast<int64_t>(get() * x);
}
// b - a == (-1 | 0 | 1) ? 0 : b > a ? [a, b) : (b, a]
int64_t get(int64_t const a, int64_t const b) noexcept {
return a + static_cast<int64_t>(get() * (b - a));
}
};
}
int main() {
Random::LCG lcg(0);
std::map<int64_t, uint64_t> buckets;
for (uint64_t i = 0; i != 1000000; ++i) {
++buckets[lcg.get(10)];
}
for (auto const [a, b] : buckets) {
std::cout << a << '\t' << b << '\n';
}
return 0;
}发布于 2018-05-27 06:51:03
this_seed = (this_seed * A + C) & M;
应该只是读
this_seed = this_seed * A + C;模块是免费为您-64位字的无符号算术。你不需要M
对于双函数[0.0,1.0),这提供了一个统一的分布:
return static_cast<double>(next() >> 11) * (1.0 / (UINT64_C(1) << 53));较少随机的低阶比特被丢弃。乘法器编译成0x1p-53。
发布于 2018-05-27 17:04:26
now函数与类无关;它只是一个助手。所以让它static。
void seed(uint64_t const value)const是可以的,但您并不是一贯地这样做。具有相同类型参数的构造函数不具有const。
https://codereview.stackexchange.com/questions/195218
复制相似问题