在Matlab中生成64位随机整数

3
我正在尝试编写一个Matlab函数,可以生成一个包含一系列64位随机整数的二进制文件。这些整数应该是高质量的,所以我希望使用64位Mersenne Twister算法或更好算法。内置的randi()函数只能产生32位数字。之前我已经使用以下方法生成了32位结果:
rng('shuffle', 'twister');
randi(2^32-1, 'uint32')

但这在64位中不可用。如果我没记错,使用多个32位整数生成64位随机整数是个不好的做法,但如果有好的解决方案,我愿意采纳。
更加困难的是,我目前正在使用一个32位的Windows XP机器。


1
这更多是一个关于统计学的问题,涉及将两个32位数字合并成一个64位数字。 - tashuhka
1
@youR.Fate 为什么将两个32位数字组合成一个64位数字被认为是不良实践? - Eitan T
正如@tashuhka所说,您不能只是连接两个32位整数的二进制表示吗?我认为您可以在数学上证明,如果这两个32位伪随机数足够好,那么64位伪随机数也将是足够好的,不是吗? - reverse_engineer
1
@Rody Oldenhis,将它们合并不是问题,因为我将它们写入二进制文件,所以我只需将它们一个接一个地写入即可。如果我没记错的话,如果你仅仅将两个32位数字连接成一个64位数字,你会失去很多质量,因为随机数生成器本身就有缺陷,而你会进一步增加这种缺陷。 - youR.Fate
@youR.Fate:顺便说一下,看看我的更新答案;我想我已经弄清楚了 :) - Rody Oldenhuis
@youR.Fate 如果一个随机数生成器在第一次生成32位数字时出现了缺陷,那么它仅通过连接32位数字来生成64位数字的方式也是有缺陷的。 - SecurityMatt
3个回答

6

似乎Matlab对64位随机整数(以及64位整数)的支持仍然相当差。

我怀疑“最佳”的解决方法是进行一些位操作:

% create 32-bit uints, and cast to 64-bit
f = @() uint64( randi([0 intmax('uint32')], 'uint32') );

% bitshift and bitor to convert into a proper uint64        
R = bitor( bitshift(f(),32), f() );

或者按照Andrew Jake的建议使用typecast,以提高可读性:
f = @() randi([0 intmax('uint32')], 'uint32');
R = typecast([f() f()], 'uint64');

创建多个随机数时,您需要将g更改为:
% bitshift and bitor: 
% ------------

% create an Nx1 uint32, and cast to 64-bit
g = @(N) uint64( randi([0 intmax('uint32')], N,1, 'uint32') );

tic
R = bitor( bitshift(g(1e7),32), g(1e7) );
toc


% typecast 
% ------------

% create a 1xN uint32, but leave the casting to typecast
g = @(N) randi([0 intmax('uint32')], 1,N, 'uint32');

tic
R = typecast([g(1e7) g(1e7)], 'uint64');   
toc

带有结果:

Elapsed time is 0.717668 seconds.    % bitor/bitshift
Elapsed time is 0.705700 seconds.    % typecast w/ loop 

它们的速度相同,所以你可以选择自己喜欢的。

Mersenne Twister主页提到当连接两个uint32时分布不会改变(感谢Andrew提供信息),因此你确实可以安全地这样做。


@EitanT:是的,我知道随机数的产品、加法等通常会产生不同的分布。但不确定这种情况…… 我认为它是相同的,对吗? - Rody Oldenhuis
你正在将两个范围不同的均匀分布数字相加。如果伪随机数生成器足够好,我想这应该没问题。 - Eitan T
2
Mersenne Twister主页似乎表明你可以这样做。请参阅FAQ页面上的“需要更高的精度”:http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/efaq.html - Andrew Janke
哦,为了更简洁(并且在我看来更易读)的类型转换,您可以在较短的整数数组上使用 typecastf = @() randi(intmax('uint32'), 'uint32'); R = typecast( [f() f()], 'uint64' ) - Andrew Janke
@AndrewJanke:好的,已更改。循环的问题实际上不是g()(我也没有使用;请参见上一次编辑),而是intmax——它不是内置的,导致JIT加速器失效并使循环变慢...啊!为什么JIT不能递归编译代码?或自动内联微不足道的函数!?或者做任何比这更聪明的事情!? - Rody Oldenhuis
显示剩余4条评论

1
这个页面来看,使用乘法滞后斐波那契生成器可能是可行的。但是按照一般标准,我认为它不会比mersenne twister表现得更好。
此外,您需要一台64位机器才能运行64位Matlab。
编辑:这个问题也表明,在默认设置下,64位版本的Matlab已经可以生成64位随机整数了。

我刚刚测试了一下:64位的Matlab中,randi函数默认不会生成uint64类型的值。当你尝试使用时,会得到相同的错误信息(即不支持uint64类型)。 - Rody Oldenhuis
Matlab的64位版本只是运行Matlab解释器的x64版本,并且可以访问更多的内存。它不会改变任何Matlab数据类型或数字功能的大小。但是那个备用生成器算法可能有效。尝试执行stream = RandStream('mlfg6331_64'); R = randi(stream, intmax('uint64'), 'uint64')。如果它能够工作,它应该可以在32位或64位的Matlab中工作。 - Andrew Janke

1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接