如何让Boost::random和Matlab产生相同的随机数
How to let Boost::random and Matlab produce the same random numbers
检查我的c++代码,我希望能够让Boost::Random和Matlab产生相同的随机数。
对于Boost,我使用代码:
boost::mt19937 var(static_cast<unsigned> (std::time(0)));
boost::uniform_int<> dist(1, 6);
boost::variate_generator<boost::mt19937&, boost::uniform_int<> > die(var, dist);
die.engine().seed(0);
for(int i = 0; i < 10; ++i) {
std::cout << die() << " ";
}
std::cout << std::endl;
生成(每次运行程序):4 4 5 6 4 6 4 6 3 4
对于matlab,我使用:
RandStream.setDefaultStream(RandStream('mt19937ar','seed',0));
randi(6,1,10)
生成(每次运行程序):5 6 1 6 4 1 2 4 6 6
这很奇怪,因为两者使用相同的算法和相同的种子。我错过了什么?
似乎Python(使用numpy)和Matlab在随机均匀数方面具有可比性:Matlab
RandStream.setDefaultStream (RandStream(‘mt19937ar’,‘种子’,203));兰德(1,10)
0.8479 0.1889 0.4506 0.6253 0.9697 0.2078 0.5944 0.9115 0.2457 0.7743
Python:random.seed (203); random.random (10)
array([ 0.84790006, 0.18893843, 0.45060688, 0.62534723, 0.96974765,
0.20780668, 0.59444858, 0.91145688, 0.24568615, 0.77430378])
c++提高
0.8479 0.667228 0.188938 0.715892 0.450607 0.0790326 0.625347 0.972369 0.969748 0.858771
这是相同的任何其他Python和Matlab值…
我不得不同意其他答案,说明这些生成器不是"绝对的"。它们可能根据实施产生不同的结果。我认为最简单的解决方案是实现自己的生成器。它可能看起来令人生畏(顺便说一下,Mersenne twister当然是),但看看Xorshift,一个极其简单但功能强大的工具。我复制了维基百科链接中给出的C实现:
uint32_t xor128(void) {
static uint32_t x = 123456789;
static uint32_t y = 362436069;
static uint32_t z = 521288629;
static uint32_t w = 88675123;
uint32_t t;
t = x ^ (x << 11);
x = y; y = z; z = w;
return w = w ^ (w >> 19) ^ (t ^ (t >> 8));
}
要拥有相同的种子,只需将您想要的任何值放入x,y,z,w(我相信除了(0,0,0,0))。您只需要确保Matlab和c++对这些unsigned int都使用32位。
使用像
这样的界面randi(6,1,10)
将对随机生成器的原始结果应用某种转换。这个变换一般来说是不是微不足道的,并且Matlab几乎肯定会执行与Boost不同的选择步骤。
尝试比较来自rng的原始数据流-它们很可能是相同的
如果这对任何对这个问题感兴趣的人有帮助:
为了获得与Twister算法相同的行为:
-
下载文件http://www.math.sci.hiroshima-u.ac.jp/m-mat每公吨/MT2002/编码/mt19937ar.c
-
尝试如下:
#include <stdint.h> // mt19937ar.c content.. int main(void) { int i; uint32_t seed = 100; init_genrand(seed); for (i = 0; i < 100; ++i) printf("%.20fn",genrand_res53()); return 0; }
-
确保在matlab中生成相同的值:
RandStream.setGlobalStream( RandStream.create('mt19937ar','seed',100) ); rand(100,1)
-
randi()
似乎只是ceil( rand()*maxval )
感谢Fezvez的回答,我已经用matlab编写了xor128:
function [ w, state ] = xor128( state )
%XOR128 implementation of Xorshift
% https://en.wikipedia.org/wiki/Xorshift
% A starting state might be [123456789, 362436069, 521288629, 88675123]
x = state(1);
y = state(2);
z = state(3);
w = state(4);
% t1 = (x << 11)
t1 = bitand(bitshift(x,11),hex2dec('ffffffff'));
% t = x ^ (x << 11)
t = bitxor(x,t1);
x = y;
y = z;
z = w;
% t2 = (t ^ (t >> 8))
t2 = bitxor(t, bitshift(t,-8));
% t3 = w ^ (w >> 19)
t3 = bitxor(w, bitshift(w,-19));
% w = w ^ (w >> 19) ^ (t ^ (t >> 8))
w = bitxor(t3, t2);
state = [x y z w];
end
每次使用时都需要将状态传递给xor128。我编写了一个"tester"函数,它只是返回一个带有随机数的向量。我用gcc测试了这个函数输出的1000个数字与cpp输出的值,它是完美的。
function [ v ] = txor( iterations )
%TXOR test xor128, returns vector v of length iterations with random number
% output from xor128
% output
v = zeros(iterations,1);
state = [123456789, 362436069, 521288629, 88675123];
i = 1;
while i <= iterations
disp(i);
[t,state] = xor128(state);
v(i) = t;
i = i + 1;
end
假设伪随机生成器的两种不同实现(即使基于相同的算法)产生相同的结果,我会非常小心。可能其中一个实现使用了某种调整,从而产生不同的结果。如果你需要两个相等的"随机"分布,我建议你要么预先计算一个序列,从c++和Matlab存储和访问,要么创建你自己的生成器。如果您使用维基百科上的伪代码,实现MT19937应该相当容易。
注意确保您的Matlab和c++代码在相同的体系结构上运行(即,两者都运行在32位或64位上)-在一个实现中使用64位整数,在另一个实现中使用32位整数将导致不同的结果。
- 理解boost::asio-async_read在无需读取内容时的行为
- 为什么随机数生成器不在void函数中随机化数字,而在main函数中随机化
- boost::进程间消息队列引发错误
- 整数不会重复超过随机数
- 如何运行位于boost/libs/python/example/tutorial目录中的hello.cpp和Jamfil
- 如何通过Boost获得0.5增量的随机数
- 使用Boost分隔接口和随机数生成器类的实现
- 有关使用 boost 生成正常随机数的问题
- 使用boost::random跨平台生成一致的随机数
- 将boost用于长二重的(伪)随机数生成器
- 使用boost生成介于1和9999之间的随机数
- Boost库-不生成不同的随机数
- boost c++正在使用Mersenne Twister算法生成0到1之间的相同随机数
- 可以在运行时选择不同的Boost伪随机数生成器
- 二维数组和boost随机数生成器
- 为什么 boost 的随机数生成(在正态分布上)总是给出相同的值?
- c++ -11中使用boost封装的随机数生成器
- C++-Boost:获取相同的随机数.播种似乎不起作用
- 如何让Boost::random和Matlab产生相同的随机数
- 如何使用boost多精度生成正常的随机数