首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >线性同余发生器的实现

线性同余发生器的实现
EN

Code Review用户
提问于 2018-05-26 12:54:43
回答 2查看 1.2K关注 0票数 1

这里有一个简单的LCG,我制作它是为了更多地了解伪随机数的生成。

这个实现正确吗?如果是的话,我如何进一步改进它?

下面的代码是自包含的,应该没有问题地运行。

代码语言:javascript
复制
#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;
}
EN

回答 2

Code Review用户

发布于 2018-05-27 06:51:03

this_seed = (this_seed * A + C) & M;

应该只是读

代码语言:javascript
复制
this_seed = this_seed * A + C;

模块是免费为您-64位字的无符号算术。你不需要M

对于双函数[0.0,1.0),这提供了一个统一的分布:

代码语言:javascript
复制
return static_cast<double>(next() >> 11) * (1.0 / (UINT64_C(1) << 53));

较少随机的低阶比特被丢弃。乘法器编译成0x1p-53。

票数 2
EN

Code Review用户

发布于 2018-05-27 17:04:26

now函数与类无关;它只是一个助手。所以让它static

代码语言:javascript
复制
void seed(uint64_t const value)

const是可以的,但您并不是一贯地这样做。具有相同类型参数的构造函数不具有const

票数 0
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/195218

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档