首先,各位不妨在新启动的MATLAB中使用randperm
生成随机整数,看看结果是否和笔者一致?
randperm
是一个返回随机整数的函数,例如 randperm(10)
以随机顺序返回从 1 到 10 的所有整数。
>> randperm(10)
ans =
6 3 7 8 5 1 2 4 9 10
尝试过的朋友们可能会发现在新启动的MATLAB中,上述命令生成的随机数是相同的,而且与MATLAB版本、操作系统等因素无关。
同样的,使用rand
、randi
、randn
等函数同样会在新启动的MATLAB会话中每次生成相同的随机数。
>> rand
ans =
0.8147
或是
>> randn
ans =
0.5377
随机数相同的原因
事实上,MATLAB中的随机数并非纯粹意义上的随机数,而是完全确定的。
不止MATLAB,其实现代编程语言和模拟平台中使用的所有“随机数”生成器(pseudorandom number generator)都是完全确定性的,是通过一定的算法使用程序生成的伪随机数, 而通过物理现象产生的随机数才是真随机数。
真伪随机数之间的最大差别在于是否可以预测。
在MATLAB中,所有随机数函数(rand
、randn
、randi
和 randperm
)均可从共享随机数生成器中取值,每次启动 MATLAB 时,生成器都会使用默认算法和种子将自身重置为相同的状态。
因此,在MATLAB 会话中启动后立即执行一个命令(例如randperm(10)
)时,会返回相同的结果。
此外,无论何时重新启动,任何调用随机数函数的脚本或函数均返回相同的结果。
所以说造成随机函数的结果取决于两点:
- 随机数生成器的算法
- 随机数生成器的种子(seed)
算法我们在下文进行详细介绍,那么种子又是什么呢?
随机数生成器的种子(seed)是初始化随机数生成器状态的一个数值。设置种子确保每次生成相同的随机数序列,这对于结果复现、调试和测试非常重要。
种子相当于随机数生成器的起点,从这个起点开始,生成器会按照确定的算法产生一系列的随机数。
种子的作用:
- 可复现性:设置相同的种子,每次运行代码时生成的随机数序列相同。这在调试和结果验证时尤为重要。
- 控制实验条件:在模拟和仿真中,使用相同的种子可以确保条件一致,便于比较不同条件的结果。
- 分布式计算:在分布式计算环境中,可以为每个子任务设置不同的种子,确保任务之间的独立性和随机性。
MATLAB的随机数算法
目前MATLAB支持的随机数生成器算法有:
1.Mersenne Twister
梅森旋转算法是 MATLAB 的默认随机数生成算法,名字源于选择梅森素数作为其周期长度。
其特点是具有非常长的周期219937-1,质量高且生成速度快,适用于大多数应用。
不仅Matlab使用其作为默认随机数算法,R、Python、Ruby、IDL、Free Pascal、PHP、Maple、GNU多重精度运算库和GSL均使用其作为默认的伪随机数算法。从C++11开始,C++也可以使用这种算法。
2. SIMD-Oriented Fast Mersenne Twister
SFMT(SIMD-oriented Fast Mersenne Twister)是梅森旋转算法的新变体,其周期同样为219937-1,支持 32 位和 64 位整数,以及双精度浮点作为输出。
在大多数平台中,SFMT 比传统的梅森旋转算法快得多,而且 v 位精度的等分布维数也得到了提高。此外,从 0 超出初始状态恢复要快得多。
3. Combined Multiple Recursive :
结合了多个递归生成器来生成随机数,周期为 2191,生成速度快且质量高,适用于并行计算。
4. Multiplicative Lagged Fibonacci
乘法时滞斐波那契生成器(MLFG),来源于时滞斐波那生成器, 使用了两个时滞斐波那契序列乘法的组合。
特点是周期较长(约 26331),随机性质量高,适合高精度需求的应用。
5. Threefry 和 Philox :
Threefry与Philox都是基于对称密钥加密技术的随机数生成器,特点是适合并行计算和 GPU 计算,提供均匀分布的高质量随机数。
Threefry 在 CPU 上速度更快,而 philox 最适合在 GPU 上使用。
Philox的周期为2193,Threefry的周期为2514。
6. 兼容旧版的生成器
还有三种支持早期版本MATLAB(4.0,5.0)的随机数生成器,分别是v4、v5uniform和v5normal。
特点是与旧版本兼容,但周期和随机性质量不如现代生成器。
比较和选择
- 性能和速度:大多数现代生成器如 Mersenne Twister、Threefry 和 Philox 在性能和生成速度方面表现出色。
- 周期长度:对于需要超长周期的应用,Mersenne Twister 和 MLFG 是优选。
- 并行计算:Threefry 和 Philox 特别适合并行和 GPU 计算,因为它们设计为能够在并行环境中提供高质量的随机数。
- 兼容性:如果需要与旧版本 MATLAB 的结果兼容,可以选择兼容旧版的生成器。
随机数生成器的设置
在 MATLAB 中,使用 rng
函数设置随机数生成器的算法和种子。
rng(seed,generator)
seed
指随机数种子,指定为小于 2^32
的非负整数或"shuffle"
。
将 seed
指定为 "shuffle"
时,rng
函数根据当前时间初始化生成器种子,在每次调用 rng
后会产生一个不同的随机数序列。
默认使用种子0初始化生成器,即
rng("default")
等效于rng(0)
generator
指随机数生成器算法,可以用传值或关键字的方法进行设置,两种方法是等效的。
默认使用Mersenne Twister算法,即
rng(0)
等效于rng(0,"twister")
%% Mersenne Twister 算法
rng(0, "twister"); %传值
rng mt19937ar %关键字
%% SIMD-Oriented Fast Mersenne Twister 算法
rng(0, "simdTwister"); %传值
rng dsfmt19937 %关键字
%% Combined Multiple Recursive 算法
rng(0, "combRecursive"); %传值
rng mrg32k3a %关键字
%% Multiplicative Lagged Fibonacci 算法
rng(0, "multFibonacci"); %传值
rng dsfmt19937 %关键字
%% Philox 算法
rng(0, "philox"); %传值
rng mt19937ar %关键字
%% Threefry 算法
rng(0, "threefry"); %传值
rng dsfmt19937 %关键字
%% MATLAB 4.0 版旧生成器算法
rng(0, "v4"); %传值
rng mt19937ar %关键字
%% SMATLAB 5.0 版旧式均匀随机数生成器
rng(0, "v5uniform"); %传值
rng dsfmt19937 %关键字
%% MATLAB 5.0 版旧式正态分布随机数生成器
rng(0, "v5normal"); %传值
rng mt19937ar %关键字
总结
MATLAB生成的随机数是确定且可控的,通过使用rng
函数设置随机数生成器(算法)与随机数种子来控制。
- 如果想在重启 MATLAB 时避免重复相同的随机数数组,在调用
rand
、randn
、randi
或randperm
之前使用rng("shuffle")
或自定义不同的随机数种子。 - 如果想在不重启 MATLAB 会话的情况下重复该会话开始时获得的结果,可使用
rng("default")
将生成器重置为启动状态。