runif()函数是否真的有一个范围:0 <= runif(n) <= 1,正如文档中所述?

5
我对R语言还不熟悉,但是文档上说runif(n)返回的数字范围在0到1之间,包括1。 我认为应该是0 <= runif(n) < 1,包括0而不包括1。
我用n=100,000,000测试了一下,发现它从未生成过0或1。我知道在浮点数中实际命中特定值的概率非常小,但是...(在双精度中0到1之间有大约2^53个值)。
因此,我查看了R的源代码,在r-source-trunk\src\nmath\runif.c中找到了答案。
do 
{
    u = unif_rand();
} while (u <= 0 || u >= 1);
return a + (b - a) * u;

所以,尽管有文档说明,它永远不会返回0或1。
这难道不是一个bug吗?

或者至少是文档存在问题吗?


1
你不能等待1或0,因为它是一个连续分布...但你可以评估u < epsilon的概率,其中epsilon是任意小的数。 - MrSmithGoesToWashington
2
我不确定你读了哪份文档,但它似乎不是我刚刚查看的官方文档help("runif")。 - Roland
1
32位的Mersenne旋转算法最多只能生成2^32个值(尽管其循环大小要大得多),因此您无论如何也不会获得所有可表示的2^53个值。您阅读的文档可能会这样说,因为在概率文献中,均匀随机变量通常被描述为具有类似于[a,b]而不是(a,b)的支持。 - John Coleman
1
WRT文档:请参见https://cran.r-project.org/doc/manuals/r-release/fullrefman.pdf,第1659页,但正如Jesse Tweedle指出的那样,我错过了它永远不会返回极值的部分。(我真的在查看rstudio中的帮助,但此时我没有它在我面前) - joeking
1
@MarkDickinson 很有道理。我没有查看源代码,但 ?RNG 很清楚内置生成器返回 2^32(或更少)个不同的值。我猜测 R 之所以这样做是出于效率方面的考虑。对于一些蒙特卡罗应用程序,随机数生成是主要的瓶颈,并且使用连续的值可能会将整个算法的速度降低近2倍。如果这真的是一个问题,用户可以指定不同定义的 RNG 的方式。肯定会有一些包提供了一个64位的twister。 - John Coleman
显示剩余2条评论
2个回答

9

在这里定义了底层的均匀随机数函数(链接),最终输出使用该函数:

static double fixup(double x)
{
    /* ensure 0 and 1 are never returned */
    if(x <= 0.0) return 0.5*i2_32m1;
    if((1.0 - x) <= 0.0) return 1.0 - 0.5*i2_32m1;
    return x;
}

尽管如此,每个生成器的返回函数都有形式为/* in [0,1) */的注释,我认为这是一个错误,与上述不符。
当然,在runif.c中注意到的代码之前还有:
/* This is true of all builtin generators, but protect against
       user-supplied ones */

所以,除了@JesseTweedle提到的情况,最小值或最大值永远不会被返回,当只调用runif()时,这种情况并不适用。

作为参考,魔数i2_32m11/(2^32-1),因此您可以从默认生成器中获得的最小值是1/(2^33-2),约为1.16e-10。最大值比该值略小1个单位。


6

文档说明:

除非max=min或max-min与min相比较小,特别是对于默认参数,runif不会生成任何极端值。

使用默认参数时,文档与您看到的行为一致。


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