c++ - 为什么 mt19937 的 STD 实现有双倍的 sizeof 作为 boost 版本?

标签 c++ random boost std mt19937

我有一个带有意外输出的简单 C++ 程序:

#include<random>
#include<iostream>
#include "boost/random/mersenne_twister.hpp"
#include "boost/random/uniform_int_distribution.hpp"

int main(){
    std::cout << sizeof(std::mt19937) << std::endl;
    std::cout << sizeof(std::mt19937_64) << std::endl;
    std::cout << sizeof(boost::random::mt19937) << std::endl;
    std::cout << sizeof(boost::random::mt19937_64) << std::endl;
}

both clang and gcc output

5000

2504

2504

2504

我发现有趣的是,mt19937(32 位)的标准实现的 sizeof 大约是 boost 版本的 2 倍,而 64 位版本完美匹配。

由于 MT 使用大量空间,因此差异确实不小。

同样奇怪的是,严格指定的算法的实现会有如此不同的 sizeof,我们不是在谈论 std::string,实现者可能会选择不同的 SSO 缓冲区大小......

我最好的猜测是 boost 要么有错误,要么它实现了一些略有不同的 mt19937 版本,但维基百科是这样说的,这表明 boost 可能是正确的:

Relatively large state buffer, of 2.5 KiB,

编辑:boost 和 std 版本似乎都是 satisfy requirement第 1000 个生成的值是 4123659995,因此 boost 似乎没有错误。

最佳答案

这是标准定义:

mersenne_twister_engine<
    uint_fast32_t, // element of the buffer
    32,
    624,           // size of the buffer
    397, 31,
    0x9908b0df, 11,
    0xffffffff, 7,
    0x9d2c5680, 15,
    0xefc60000, 18, 1812433253>

问题是 GNU 选择 std::uint_fast32_t 是 64 位系统上的 64 位类型(这是一个好的还是坏的选择是单独的讨论)。因此,如果缓冲区包含 32 位整数,则缓冲区的大小是预期的两倍。

这是 Boost 定义:

mersenne_twister_engine<
    uint32_t,
    32,
    624,
    397, 31,
    0x9908b0df, 11,
    0xffffffff, 7,
    0x9d2c5680, 15,
    0xefc60000, 18, 1812433253>

除了使用在所有系统上始终相同的固定宽度元素外,它们是相同的。


您可以将 std::mersenne_twister_engine 直接与 std::uint_least32_t 元素一起使用来解决此问题。使用此别名优于固定别名,因为所有系统都需要支持它。

关于c++ - 为什么 mt19937 的 STD 实现有双倍的 sizeof 作为 boost 版本?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63601328/

相关文章:

C++:如何从数组生成随机数

c++ - 关于多线程客户端的 BOOST 教程?

c++ - 如何使 boost::apply_visitor 成为类访问者的友元函数?

c++ - 函数类型参数的模板参数推导

c++ - 将字母表示为 2 位数字,将大数字转换为单词

C++ 为什么需要在扩展类中指定函数的作用域?

c++ - 自动推断 bind1st(mem_fun(&my_class::f), this) 的类型?

java - 不包括零的范围内的随机数

c++ - rand () for c++ with variables

c++ - 如何检查 SSL 套接字是否关闭(异步)