为什么需要两个随机变量来保证使用sample()函数在大整数中进行均匀采样?

11

考虑到以下内容是等价的,我们可以推断出 R 使用相同的 C runif 函数来为 sample()runif() 生成均匀分布样本...

set.seed(1)
sample(1000,10,replace=TRUE)
#[1] 27 38 58 91 21 90 95 67 63  7

set.seed(1)
ceiling( runif(10) * 1000 )
#[1] 27 38 58 91 21 90 95 67 63  7

但是,当处理大数字(n > 2^32 - 1)时,它们并不等价:

set.seed(1)
ceiling( runif(1e1) * as.numeric(10^12) )
#[1] 265508663143 372123899637 572853363352 908207789995 201681931038 898389684968
#[7] 944675268606 660797792487 629114043899  61786270468

set.seed(1)
sample( as.numeric(10^12) , 1e1 , replace = TRUE )
#[1] 2655086629 5728533837 2016819388 9446752865 6291140337 2059745544 6870228465
#[8] 7698414177 7176185248 3800351852

更新

正如@Arun所指出的那样,runif() 的第1、3、5个...结果大致相当于从 sample() 中的第1、2、3个...结果。

事实证明,两个函数在幕后都调用了unif_rand(),然而,sample在给定一个参数n时,若该参数大于类型"integer"的最大可表示整数但可以表示为类型"numeric",则使用这个静态定义来绘制随机偏差(与 runif()的情况不同,后者仅使用unif_rand())...

static R_INLINE double ru()
   {
       double U = 33554432.0;
       return (floor(U*unif_rand()) + unif_rand())/U;
   }

在文档中有一段神秘的注释,其中...

使用两个随机数可确保对大整数进行均匀抽样。

  • 为什么需要两个随机数才能确保对大整数进行均匀抽样?

  • 常量U是什么,为什么它取特定值33554432.0


3
在这个语境中,“correct”是指什么?这些应该是随机的(当然它们只是“伪随机”,但仍然如此)。 - gung - Reinstate Monica
4
正在寻找...啊哈:https://dev59.com/kWMk5IYBdhLWcg3w2ReT#18908655 - Carl Witthoft
1
谷歌搜索“33554432 PRNG”会出现一些有用的(?)东西。 - Ben Bolker
1
33554432等于2的25次方。 - Ben Bolker
1
@BenBolker 啊,这就解释了在那个定义之前源代码中的 /* 我们的伪随机数生成器最多有32位精度,且所有生成器至少有25位 */。谢谢。 - Simon O'Hanlon
显示剩余4条评论
1个回答

2

原因是25位伪随机数生成器(PRNG)无法生成足够的比特以在宽于2^25的范围内生成所有可能的整数值。为了给每个可能的整数值一个非零概率,需要调用25位PRNG两次。使用两次调用(如您引用的代码中),可以获得50个随机比特。

请注意,double具有53位尾数,因此调用PRNG两次仍然短缺3个比特。


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