主要内容
概率和非均匀分布
还记得你第一次在这里开始编程吗?也许你当时想在屏幕上画很多圆。你对自己说:“哦, 我知道。我要在随机位置用随机大小和随机颜色来画所有的圆。”在计算机图形系统中,使用随机种子通常是最简单的。然而,在这些课程中,我们希望建立模拟在自然界中看到的东西的系统。对于设计问题,尤其是涉及创建有机或自然外观模拟的问题,拒绝随机性并不是一个特别深思熟虑的解决方案。
通过一些技巧,我们可以改变使用
random()
生成“非均匀”分布的随机数的方式。这将在本课程中派上用场,因为我们将看到一些不同的场景。例如,当我们检查基因算法时,我们需要一种执行 “选择” 的方法——应该选择哪些人口成员将他们的 DNA 传递给下一代?还记得适者生存的概念吗?假设我们有大量的猴子在进化。不是每只猴子都有平等的繁殖机会。为了模拟达尔文进化论,我们不能简单地随机选择两只猴子作为父母。我们需要让更"合适"的猴子更有可能被选中。我们需要定义"适者生存的概率"。例如,一个特别快和强壮的猴子可能有 90% 的机会生育,而较弱的猴子只有 10% 的机会。让我们在这里暂停一下,看看概率的基本原理。首先,我们将检查单个事件概率,即给定事件发生的可能性。
如果你有一个系统,它有一定数量的可能结果 并且 每个结果都有相同的发生机会,那么一个给定事件发生的概率等于符合该事件的结果数除以所有可能的结果总数。抛硬币就是一个简单的例子——它只有两种可能的结果,正面或者反面。只有一种方法可以翻到正面。因此,硬币出现正面的概率是一除以二:1/2 或 50%。
拿一副五十二张牌。从一副牌中上抽出尖儿(A)的概率是:
尖儿的数量 / 牌的总数 = 4 / 52 = 0.077 = ~ 8%
抽出方块的概率为:
方块的数量 / 牌的总数 = 13 / 52 = 0.25 = 25%
我们还可以计算序列中发生多个事件的概率。要做到这一点,我们只需将每个事件的概率相乘。
硬币连续三次出现正面朝上的概率是:
(1/2) * (1/2) * (1/2) = 1/8 (或 0.125)
这意味着硬币连续三次正面朝上 每八次会出现一次 (每 “次” 是扔三下)。
有几种方法可以让我们在代码中使用具有概率的
random()
函数。一种方法是用选定的数字填充数组(其中一些数字是重复的), 然后从该数组中选择随机数并根据这些选择生成事件。运行此代码将产生 40% 的可能输出 1,20% 的可能输出 2,40% 的可能输出 3。
我们还可以寻求一个随机数(为了简单我们只考虑 0 到 1 之间的随机小数),并且只有当我们的随机数在一定范围内时,事件才发生。查看下面的示例,并持续点击重新启动(restart)直到随机选取的数字小于阈值:
此方法也可应用于多个结果(outcome)。假设结果 A 发生的几率为 60%,结果 B 有 10% 的几率,结果 C 有 30% 的几率。我们通过选择一个随机数并查看它的范围来实现这一点。
- 在 0.00 和 0.60 (60%) 之间 –> 结果 A
- 在 0.60 和 0.70 (10%) 之间 –> 结果 B
- 在 0.70 和 1.00 (30%) 之间 –> 结果 C
点击重新启动按钮,查看获得不同结果的频率:
我们可以使用上面的方法来创建一个随机步行者(walker),倾向于向右移动。下面是具有以下概率的
Walker
的示例:- 向上移动的可能性:20%
- 向下移动的可能性:20%
- 向左移动的可能性:20%
- 向右移动的可能性:40%
“自然模拟”系列课程是由 Daniel Shiffman 的 "编程的本质" 衍生而来,基于 知识共享 著名-非商用性 3.0 本地化许可协议。