要检查我的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值相同......
答案 0 :(得分:4)
使用
这样的界面randi(6,1,10)
将对随机生成器的原始结果应用某种转换。这种转换 is not trivial in general 和Matlab几乎肯定会做出与Boost不同的选择步骤。
尝试比较来自RNG的原始数据流 - 它们可能是相同的
答案 1 :(得分:4)
我必须同意其他答案,并指出这些发电机不是“绝对的”。根据实施,它们可能产生不同的结果。我认为最简单的解决方案是实现自己的生成器。它可能看起来令人生畏(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));
}
要拥有相同的种子,只需将所需的值放入int x,y,z,w(我相信除了(0,0,0,0))。您只需要确保Matlab和C ++对这些unsigned int使用32位。
答案 2 :(得分:3)
如果这有助于任何对此问题感兴趣的人:
为了获得Twister算法的相同行为:
下载文件 http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/MT2002/CODES/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("%.20f\n",genrand_res53());
return 0;
}
确保在matlab中生成相同的值:
RandStream.setGlobalStream( RandStream.create('mt19937ar','seed',100) );
rand(100,1)
randi()
似乎只是ceil( rand()*maxval )
答案 3 :(得分:1)
感谢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。我写了一个&#34;测试员&#34;只返回带有随机数的向量的函数。我测试了这个函数输出的1000个数字对cpp和gcc输出的值,它是完美的。
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
答案 4 :(得分:0)
我会非常小心地假设伪随机生成器的两种不同实现(即使基于相同的算法)产生相同的结果。可能有一个实现使用某种调整,因此产生不同的结果。如果您需要两个相等的“随机”分布,我建议您预先计算序列,存储和访问C ++和Matlab,或者创建自己的生成器。如果在Wikipedia上使用伪代码,那么实现MT19937应该相当容易。
注意确保Matlab和C ++代码在相同的体系结构上运行(即,无论是在32位还是64位上运行) - 在一个实现中使用64位整数,在另一个实现中使用32位整数导致不同的结果。