如何在R中生成介于0和1之间但不包括0和1的随机数?

5
我想在R中使用runif(n=1,min=0,max=1)生成随机数,但是我不想要0和1这两个点,我该如何修改才能达到我的目标?
我认为它确实以某种方式生成了1,可以看到我的代码:
randomDim = round(runif(1)*3)+1;randomDim

  # [1] 4

1
0和1是默认值,只需执行runif(1)即可。 - David Arenburg
2
你的例子与 runif 没有任何关系,而与 round 有关。?roundDetails 部分解释了如何得到结果为4。 - Joshua Ulrich
@JoshuaUlrich,有什么建议可以解决这个问题吗? - user4592991
2
如果你确实想要在区间1-3内生成一个随机整数(正如你的代码所示),那么sample(1:3,1)就可以实现。 - Pewi
什么问题?roundrunif都在按照它们所记录的方式执行,而且runif默认情况下会按照你在问题中所要求的方式执行。 - Joshua Ulrich
1
@Pewi,我认为你应该把你的评论发表为答案。这是对原帖真正问题的回答... - Ben Bolker
6个回答

20

关于 runif 的文档声明:

除非输入的参数满足 'max=min' 或者 'max-min' 相对于 'min' 来说很小,否则 'runif' 函数不会产生极值。特别地,默认参数情况下也不会产生。

因此, 'runif' 已经保证不会生成0或1,因此不需要进行修改。


我认为它确实生成了一些东西,可以看看我的代码:randomDim = round(runif(n=1, min = 0, max = 1)*3)+1;randomDim [1] 4 - user4592991
2
为什么这表明它会生成1?如果它生成大于2.5/3.0 = 0.833...的任何值,输出结果将是4。 - Brent Kerby
range(runif(n = 1e8))给出了[1] 4.889444e-09 1.000000e+00,因此1是可能的... - Dominic Comtois
@DominicComtois,我认为不完全正确:1-max(runif(n = 1e8)) 的结果是3.958121e-09。 - Ben Bolker
4
@DominicComtois说:"1.000000e+00"不等于"1.0"。在设置种子为21的情况下,生成一亿个均匀分布的随机数并计算它们的范围,然后使用sprintf函数将其格式化为20位小数的字符串。结果如下: - Joshua Ulrich
好的,那是令人信服的证据 ;) - Dominic Comtois

4
也许可以这样简单地表达?
runif(n=1, min=1e-12, max=.9999999999)

7
不必要。默认情况下,“runif”不包括端点值。 - Joshua Ulrich

2

按照大众要求: sample(1:3,1) 可能是解决您问题的答案。 它与 runif 没有任何关系,但提供了通常称为一、二和三的整数中的任意一个,各自的概率为 1/3。


2

尝试 sample(1:9, 1000, replace = TRUE)/10

所以你正在从1到9随机生成数字,并对其使用分数。


1

除了上述列出的选项之外,另一种选择是使用Beta分布生成您的数字。

具有shape1=1shape2=1参数的Beta分布将为您提供平坦(即均匀)分布,其在0和1处在数学上受到限制(即不可能取任何一个值)。

rbeta(n, 1, 1)

另外,你不喜欢结果中有多少部分来自于使用round()函数?

我问这个问题,因为如果你运行round(.97*3)+1,你会得到一个值为4。同样,如果你运行round(.005*3)+1,你会得到1。两个值.97.005都是runif()可以合理返回的合法值。因此,你不想要的结果可能与runif()在其默认极端值返回值无关(正如其他答案中指出的那样,这些值不包括在采样值的范围内)。

无论如何,如果你仍然不信服并想要使用其他替代方案而非runif,那么形状参数为1的beta分布在数学上确保你永远不会得到1或0,使用该参数化,你将有等概率从rbeta(n,1,1)分布中绘制介于0和1之间的任何值。


0

由于在 Brent Kerby 的回答下有一些讨论,如果有疑问,您可以随时检查源代码

double runif(double a, double b)
{
    if (!R_FINITE(a) || !R_FINITE(b) || b < a)  ML_ERR_return_NAN;

    if (a == b)
    return a;
    else {
    double u;
    /* This is true of all builtin generators, but protect against
       user-supplied ones */
    do {u = unif_rand();} while (u <= 0 || u >= 1);
    return a + (b - a) * u;
    }
}

因此,“如果”算法拒绝所有小于或等于零和大于或等于一的值...确切的零和一是不可能的。如Ben Bolker所指出的那样,接近它们的值在浮点精度范围内是可能的。


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