我想知道如何使用“基本操作”对随机变量进行建模。我知道的唯一一个随机函数,至少对于C来说,rand()
和srand
用于播种。可能存在在线某处的软件包,但我想说我想自己实现它。我不知道是否还有其他非常常见的随机函数,但如果没有,我们只需坚持使用rand()
和C语言。
rand()
允许我从int
到0
伪随机生成RAND_MAX
。然后,我可以使用mod
在某个范围内获得int
。我可以接下来mod 2
选择一个标志并获得负数。我还可以rand()/RAND_MAX
对(0,1)
区间内的值进行建模,并将其转换为模型Uniform(a,b)
。
但我不确定的是,我是否可以将其扩展到模拟任何概率分布,以及在什么时候我必须担心准确性,特别是在处理无穷大和非理性概率时。此外,这种方法非常粗糙,所以我想知道使用基本工具的更多标准方法(如果有的话)。
一个简单的例子:
我有随机变量X
,Pr(X = 1)=1/pi
和Pr(X=0)=1-1/pi
。由于pi
不合理,我会估算1/pi
获得rand()
的可能性,如果我从X=1
获得int
,则选择0
Round(RAND_MAX*1/pi)
。所以这是近似两次,一次是pi
,另一次是四舍五入。
有更好的方法吗?如何建模更复杂的东西,例如区间(0,infinity)
上的连续随机变量,或者在可数无限集上具有无理概率的离散随机变量。我的方法是否仍然可行或者我不得不担心舍入错误?
编辑:另外,伪随机性而不是rand()
的随机性如何改变事物以及如何解释这些变化?
答案 0 :(得分:7)
不,你不能。用骰子试试吧。你想要一个1到5之间的数字。所以你采用roll mod 5(实际上它是然后我可以使用mod来获取某个范围内的int
((roll-1)%5)+1
)。这会将1到1,2到2等映射到5到5和6到1.现在你的可能性是其他任何一卷的两倍。
这样做的正确方法是找到比你的范围高2的最接近的幂,掩盖高于2的幂的随机数的位,然后检查你是否在范围内。如果您不在范围内,请再试一次(可能会永远循环,实际上平均重试次数小于2)。这假设您的随机数是比特流而不是其他内容。对于体面的发电机来说,这通常是一个安全的假设。
不,你不能。这不是浮点数的工作原理。这会产生可怕的分布。我也可以用rand()/ RAND_MAX来模拟区间(0,1)中的值
整数中的位数小于尾数中的位数,那么你只需要一堆你不能生成的浮点数。或者整数中的位数大于尾数中的位数,然后在分割之前将其转换为浮点时截断整数,并且会更频繁地生成某些数字。
在区间(0,1)中并将其移至模型Uniform(a,b)。
这使事情变得更糟。首先,你在一个方向丢失了比特,然后你在另一个方向丢失了比特。
实际生成任意范围内均匀分布的浮点数比看起来更难。
几年前我已经做了一些实验来自己解决这个问题,在这个过程中学习了浮点内部,我在这里编写了一些带有很多评论的代码:https://github.com/art4711/random-double
简而言之,要在任意范围内生成随机浮点数:找到范围的较大绝对值。这是开始,范围的另一端是结束。从头到尾找出下一个可表示的数字。从开始减去下一个数字,成为步骤。计算开始和结束之间存在的步数。生成0到步数之间的均匀分布的随机数。开始+步骤*随机数就是答案。此外,由于浮点的工作原理,这可能不是您正在寻找的。使用此方法无法生成所有可能的浮点值(非常特殊情况除外)。但是这种方法可以保证每个可能的值同样可能。
请注意,您的误解很常见。几乎每个人都做这些事情。行业中的随机数不是随机数。计算机科学中的随机一词几乎意味着“可预测,可重复,易破解和可利用,很可能分布不均”。并且不要让我开始使用标准库中“随机”数字生成器的质量。如果你在我的github周围挖掘东西,你会发现Go的一个包,并且有很长的README咆哮。
我不打算回答你的其他问题,这些内容需要一两本书。