主要内容
随机数的自定义分布
在你的生活中,会有一个时刻,你不想要一个均匀分布的随机值,或是一个高斯分布的。让我们想象一下,你是一个随机的在寻找食物的路人。在一个空间里随机的移动像是一个寻找食物的合理策略。毕竟,你不知道食物在哪里,还不如随机搜索知道你找到它。正如你可能已经注意到的,问题在于这个随机的路人会多次返回到曾经来过的地点(这被称为“过度采样”)。其中一个避免这个问题的策略是每隔一段时间就迈出非常大的一步。这使得这个路人可以在特定地点的周围随机觅食,同时周期性的跳出很远来避免过度采样。随机行走的这种变化(被称为莱维飞行)需要一组自定义的概率。随着这不是莱维飞行的准确实施,我们可以这样设置概率分布:当步距越长,被选择的可能性就越小;当步距越短,可能性就越大。
在本节前面的部分中,我们看到,我们可以通过填充数组(有些重复的值以提高它们被选中的几率)或测试
random()
的结果来生成自定义的概率分布。我们可以通过将路人迈一大步的几率设为1%来实现莱维飞行。var r = random(1);
// 1%的几率迈一大步
if (r < 0.01) {
xstep = random(-100, 100);
ystep = random(-100, 100);
} else {
xstep = random(-1, 1);
ystep = random(-1, 1);
}
然而,这会将概率减低到固定数量的选项。如果说我们想要制定一个更笼统的规则呢——一个数字越大,它被选择的可能性就越大?3.145 比 3.144 更有可能被选中,即使这个可能性只大了一点点。换句话说,如果
x
是一个随机数,我们可以用 y
= x
来将对应的可能性映射到 y 轴上。如果我们可以根据上图找到如何生成随机数的分布,我们就可以将同样的方法用到任何我们知道公式的曲线上。
一种解决方案是选择两个随机数,而不是一个。第一个随机数就只是一个随机数。而第二个是我们所说的”符合条件的随机值“。它会告诉我们是使用第一个随机值还是将它扔掉并选择另外一个。更容易符合条件的数字将会被更频繁的选择,而很少符合条件的数字则会很少被选择。这是执行的步骤(现在我们只考虑0到1之间的随机值):
- 选择一个随机值:R1
- 计算 R1 要满足的概率 P。让我们试试:P = R1。
- 选择另一个随机值:R2
- 如果 R2 小于 P,我们则已经找到了我们的数字—— R1!
- 如果 R2 不小于 P,就返回到步骤1并重新开始。
在这里我们假设了一个随机值符合条件的概率等于这个随机值本身。假如 R1\ 为 0.1。这表示 R1 会有10%的机率符合条件。假设 R1 为 0.83,则它会有83%的机率符合条件。数字越大,我们实际使用它的可能性就越大。
“自然模拟”系列课程是由 Daniel Shiffman 的 "编程的本质" 衍生而来,基于 知识共享 著名-非商用性 3.0 本地化许可协议。