我有一个简单的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;
}5000 二五零四 二五零四 二五零四
我发现有趣的是,mt19937(32位1)的大量标准实现大约是boost版本的2倍,而64位的则完全匹配。
由于MT使用了大量的空间,这并不是一个很小的区别。
同样奇怪的是,严格指定的算法的实现会有如此不同的大小,我们不是在谈论std::string,其中实现者可能选择不同的SSO缓冲区大小.
我最好的猜测是boost要么有一个bug,要么它实现了一些稍微不同的mt19937版本,但维基百科说,这表明boost可能是正确的:
相对较大的状态缓冲器,2.5 KiB,
编辑: boost和std版本似乎都是满足要求的第1000生成值是4123659995,所以在boost中似乎没有bug。
发布于 2020-08-26 16:25:39
这是标准定义:
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元素来解决这个问题。使用这个别名比固定别名更可取,因为它需要在所有系统上得到支持。
https://stackoverflow.com/questions/63601328
复制相似问题