如何使用生成一个浮点数在 [0.0, 1.0) 范围内的随机数生成器来产生一个在 [1, n] 范围内的随机数?

6
假设你有一个随机数生成器,它生成一个介于[0.0, 1.0)之间的随机浮点数,例如drand48,那么如何创建一个随机数生成器来生成介于[1, n]之间的整数?

我认为 drand48 生成的数字是从 [0,1] 而不是 [0,1) 中产生的,那么你真正拥有什么呢?是的,这很重要。 - Christian Rau
或许有一个基本的假设,即分布应该是均匀的,值得明确说明(或否认)。虽然Open Group文档将drand48的范围定义为[0.0,1.0]上的均匀分布,但返回1.0的相应概率是可以忽略不计的。为了精确起见,我们可能需要调用drand48,直到获得小于1.0的结果。 - hardmath
可能是解释Math.random()的重复问题。 - starblue
4个回答

11

将其乘以n,向下取整,再加1。


1
由于输入始终为正数且输出为整数,因此强制转换为“int”比使用“floor”更好。 - Mark Ransom
@Jason,请问你说的“take the floor”是什么意思,我不是英语母语人士。 - ob_dev
1
@oussama:一个数x的floor是最大的整数n,使得n <= x。 - Andreas Rejbrand
@AndreasRejbrand 这相当于在C中的n = (long)x,对吗? - ob_dev
@oussama:抱歉,我不太了解C语言,无法回答这个问题,我会让其他人来回答。特别是,我不知道如果x < 0会发生什么。不过,你肯定可以使用数学库中的常规floor、ceil和round函数吧? - Andreas Rejbrand
1
将浮点数或双精度数转换为整型会截断小数部分,对于 x >= 0,结果相当于向下取整,而对于 x <= 0,则相当于向上取整。 - Daniel Fischer

0

取随机数生成器的结果,乘以n-1,再加上1。


由于1.0不包括在内,因此“n”将是更好的因子。 - Christian Rau

-2

在C语言中的示例:

long rand(int n)
{
    double rand1 = 0;

    rand1 = drand48();
    rand1 *= n - 1;
    rand1 += 1;

    return  (long)rand1;
}

1
你的代码有一个缺点,就是它不是线性(或至少单调)转换。但除了这个小缺陷之外,它甚至在不保证[1,n]的情况下是不正确的。 - Christian Rau
1
它可以对于任何足够小的 rand1 产生 0。 - Christian Rau
如果使用 drand48(它生成 [0,1],尽管 OP 要求的是 [0,1) ,但他也引用了 drand48),将其乘以 n-1 再加 1 将是一个更好的选择。虽然会有一点偏向于较低的端点,但至少它是单调的且范围在 [1,n]。 - Christian Rau
您的更新现在可以为任何足够大的rand1生成2n-1。只需摆脱这个if并进行简单的线性转换,记住rand1是来自[0,1]的双精度数。 - Christian Rau
现在它是正确的,虽然使用双引号字面量而不是整数会更清晰,但没关系。但我的反对票仍然存在,因为它是错误的答案太长时间,并需要广泛的帮助(实际上足以成为自己的问题)才能得到纠正。 - Christian Rau

-3

我相信你可以拥有不同的随机数生成器。

Multiply by n, take the int, and add 1.

对不起,我在写另外一件事情。 - RG-3
我希望另一个答案中的完美字面引用只是巧合! - Christian Rau
是的。他比我快了1秒钟。我也在想同样的事情。 - RG-3
1
你为什么要复制粘贴我的答案? - jason
@klm9971 那么你的回答只是想要先占据优势并稍后更新更多信息吗?你真的认为使用完全相同的词语吗?我不太理解你的第二种解决方案。 "拿双倍"是什么意思?您是否意味着乘以2? - Christian Rau
显示剩余4条评论

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