randi和rand之间有什么联系?

时间:2018-09-04 12:07:21

标签: matlab

我正在R2012a版本上运行。我试图编写一个使用randi(仅rand)来模仿rand的函数,当传递相同的参数并提供相同的种子时产生相同的输出。我在命令窗口中尝试了一些东西,这就是我得到的:

>> s = rng;
>> R1 = randi([2 20], 3, 5)

R1 =

     2    16    11    15    14
    10    17    10    16    14
     9     5    14     7     5

>> rng(s)
>> R2 = 2+18*rand(3, 5)

R2 =

    2.6200   15.7793   10.8158   14.7686   14.2346
    9.8974   16.3136   10.0206   15.5844   13.7918
    8.8681    5.3637   13.6336    6.9685    4.9270

>> 

快速的比较使我相信两者之间存在某种联系:R1中的每个整数与R2中相应元素的正负单位一致。但是,我没有做进一步的事情:我检查了天花板,地板,固定和倒圆角,但是它们似乎都没有作用。

1 个答案:

答案 0 :(得分:2)

randi([2 20])生成2到20之间的整数,都包含在内。也就是说,它可以生成19个不同的值,而不是18。

19 * rand

生成在半开间隔[0,19]内均匀分布的值,对它进行下铺将为您提供[0,18]范围内的均匀分布整数。

因此,通常

x = randi([a,b]]);
y = rand * (b-a+1) + a;

应产生具有相同属性的数字。从OP的实验看来,它们可能会生成相同的序列,但这不能保证,也可能不会。

为什么? randi可能不是以rand的形式实现的,但是它是底层的随机生成器,生成整数。要从较大范围(x)的随机整数[0,N-1]到较小范围([0,n-1])的整数,通常应使用模运算符(mod(x,N))或类似上述的下限划分法,但请删除会使分布偏斜的一小部分值。 This other anser进行了详细说明。我喜欢从示例的角度来思考它:

说随机值在[0,2^16-1]N=2^16)范围内,而您希望在[0,18](n=19)范围内。 mod(19,2^16)=5。也就是说,可以由随机数生成器生成的最大5个值映射到输出范围的最低5个值(假设取模方法),与其余的输出范围相比,这些数字生成的可能性更高。这些最低的5个值有机会floor(N/n)+1,而其余的有机会floor(N/n)。这是不好的。 [使用底数除法而不是模数会得出不均匀性的不同分布,但是最终结果是相同的:某些数字比其他数字更可能出现。]

要解决此问题,正确的实现方式如下:如果您在随机生成器中获得floor(N/n)*n或更高的值之一,则需要丢弃它并重试。当然,对于使用N=2^64的典型随机数生成器来说,这是很小的机会。

尽管我们不知道randi的实现方式,但是我们可以肯定它遵循此处描述的正确实现。因此,基于rand的序列可能适合数百万个数字,但随后开始偏离。


有趣的是,Octave的randi被实现为M文件,因此我们可以看到它们是如何实现的。事实证明,它基于rand使用了该答案顶部显示的错误算法:

 ri = imin + floor ( (imax-imin+1)*rand (varargin{:}) );

因此,八度的randi有偏见!

相关问题