2017-02-21 87 views
4

我想知道如何使用“基本操作”为随机变量建模。我知道的唯一随机函数,至少对于C来说,是rand(),以及用于播种的srand。可能存在某些在线的软件包,但可以说我想自己实现它。我不知道是否还有其他非常常见的随机函数,但如果不是,只需坚持使用rand()和C语言。如何模拟随机变量?

rand()允许我从0RAND_MAX伪随机生成int。然后我可以使用mod在某个范围内获得int。我可以下mod 2选择一个标志并获得负数。我也可以使用rand()/RAND_MAX来模拟间隔(0,1)中的值,并将其转换为Uniform(a,b)

但是我不确定的是,如果我可以扩展它来模拟任何概率分布,以及在什么时候我必须担心精度,特别是在处理无穷大和无理概率时。此外,这种方法非常粗糙,所以我想知道更多使用基本工具的标准方法(如果有的话)。

一个简单的例子:

我有随机变量X使得Pr(X = 1)=1/piPr(X=0)=1-1/pi。由于pi不合理,因此我会近似得到1/pirand()的概率,并选择X=1,如果我从0获得intRound(RAND_MAX*1/pi)。所以这是近似两次,一次为pi,另一次为四舍五入。

有没有更好的方法?人们会怎样去模拟一些更复杂的事情,如间隔(0,infinity)上的连续随机变量,或者一个离散的随机变量,它们在可数无限集合上具有无理概率。我的方法仍然有效吗?还是我不得不担心舍入错误?

编辑:另外如何伪随机性而不是随机性的0​​改变的事情,我将如何解释这些变化?

+1

*“我可以使用mod在一定范围内获得int。”*不可以。你必须划分,而不是使用mod,因为你只会使用较低的位,而这些位较少随机。 – spectras

+2

@spectras无法保证'rand'的质量。因此,不确定低位或高位是否“更随机”。事实是,如果你需要任何种类的真正的随机分配,“兰特”是一个不行。哦,除非输入范围是除数的整数倍,否则div和mod都不适用。 – Olaf

+3

我觉得这个问题或多或少需要一个演讲作为答案。这并没有错,并且已经有这样的讲座史诗般的案例被传递,但它也(从字面上)要求很多。 :) – unwind

回答

7

然后我就可以使用国防部在一定范围内

没有得到一个int,你不能。用骰子尝试。你需要一个介于1和5之间的数字。所以你采取滚动模5(种类,它实际上是((roll-1)%5)+1)。这会将1映射到1,2到2等,5到5和6到1.您现在有1倍于其他任何卷的可能性的两倍。

这样做的正确方法是找到距离范围更近的2的最近幂,掩盖2以上的随机数的位,然后检查是否在范围内。如果你不在范围内,再试一次(可能会永久循环,实际上平均重试次数小于2)。这假定你的随机数是一串比特而不是别的。对于像样的发电机这通常是一个安全的假设。

我还可以做兰特()/ RAND_MAX到值在区间(0,1)

无不是模型,您可以。这不是浮点数的工作方式。这产生了一个可怕的分布。

要么是整数中的位数小于尾数中的位数,那么您只会得到一堆您无法生成的浮点数。或者整数中的位数大于尾数中的位数,然后在分割之前将整数转换为浮点数时会截断整数,并且会更频繁地生成某些数字。

在区间(0,1)中,并将其移到模型Uniform(a,b)。

这使事情变得更糟。首先你在一个方向丢失比特,然后你在另一个方向丢失比特。

实际上在任意范围内生成均匀分布的浮点数比看起来要困难。

我已经做了一些实验,几年前这出自己,学习浮点内部在这个过程中,我已经写了一些代码有很多与推理在这里评论:https://github.com/art4711/random-double

总之,在任意范围内生成随机浮点数:找到范围中较大的绝对值。这是开始,范围的另一端是结束。找出从开始到结束的下一个可表示数字。从开始减去下一个数字,即成为步骤。计算开始和结束之间存在多少步骤。生成一个介于0和步数之间的均匀分布的随机数。开始+步骤*随机数是答案。另外,由于浮点运算的原因,这可能不是你正在寻找的。所有可能的浮点值绝对不可能使用此方法生成(除非是非常特殊的情况)。但是这种方法保证了每个可能的值都是相同的。

请注意,您的错误观念非常普遍。几乎每个人都会做这些事情。该行业的随机数字不是随机的。计算机科学中的随机词几乎意味着“可预测,可重复,容易破解和可利用,很可能分布不均”。不要让我开始关注标准库中“随机”数字生成器的质量。如果你围绕我的github东西进行挖掘,你会发现一个关于这个的长篇README咆哮的Go包。

我不打算回答你的问题的其余部分,这些位需要一两本书。

+0

任何好的参考?谢谢。 – domoremath

+0

@domoremath并非如此。这仅仅是我多年来编写代码并与加密人(那些痴迷于好随机数的人)联系在一起的知识。起点是认识到,仅仅因为我们使用运算符'+',''','*'和'/'并不意味着它们在真正的数学中表现得如此。尤其是没有浮点。其余的只是阅读标准和文档,看看实际情况如何。 – Art