主要内容
随机数的正态分布
假设我们想做那个生成猴子世界的程序。你的程序可以生成一千个猴子,每个猴子的身高值介于200到300之间 (因为这个猴子世界的猴子高度在200到300像素之间)。
var randomHeight = random(200, 300);
这是否准确地反映了真实世界呢?想象纽约一条拥挤的人行道。随便从中挑选一个人,他的身高是随机的。然而,这个随机与我们程序语言中的随机
random()
不同。 人的身高不是机械分布的,大多数人的身高处于平均水平,特别高或特别矮的人很少。为了更贴近现实,我们想要得到的结果是猴子的身高基本上处于平均值(250 像素),但也会有极少的很高或很矮的情况。数值集中在平均数 (通常用 “均值”表示) 附近的分布称为 “正态” 分布。也称为高斯分布 (以数学家 Carl Friedrich Gauss命名),如果你是法国人,所说的拉普拉斯分布 (以 Pierre-Simon Laplace命名)也是指的同一个内容。这两位数学家在19世纪早期致力于对这样分布的研究,互相补充,更好地定义了这种分布。
当您画正态分布图形时,你会画出类似下图的,常说的钟形曲线:
该曲线是由一个数学函数生成的,也就是一个将任意变量出现的概率表示为平均值 (常写为 μ,希腊字母 mu) 和标准差 (σ,希腊字母 sigma)的函数。
平均值很容易理解。在我们的猴子例子中,猴子身高值在200到300之间,你可能直观地感觉到平均值 (即均值) 为25。然而,如果我说标准差是3或15呢?这些数字意味着什么?看看这些图可以给我们一个直观提示。上图是标准差很小的分布,其中大多数值都在于平均值很近的附近。下图是标准差较大的分布,其中的数值与平均值的距离远近更为均匀:
不熟悉 "标准偏差" 的概念?不用担心!你可以在汗学院分别学习方差和标准差 ,然后再回来继续。
这些数值表示的情况如下:给定一个样本,对象数值位于与平均值相差一个标准差范围内的对象有68% ,对象数值位于两个标准差范围内的对象有95% ,有99.7% 的对象取值都是位于三个标准差区间内。如果标准差是5个像素,那么只有0.3% 的猴子高度是小于235像素(低于平均值250三个标准差)或大于265像素(高于平均值250三个标准差)。
计算平均值和标准差
以十个学生为例,他们的考试分数如下 (总共参加考试的学生是100名):
85, 82, 88, 86, 85, 93, 98, 40, 73, 83
我们通过汇总所有分数并除以选取的学生数来计算平均值 (平均数)。
平均值 = left parenthesis, 85, plus, 82, plus, 88, plus, 86, plus, 85, plus, 93, plus, 98, plus, 40, plus, 73, plus, 83, right parenthesis, slash, 10, equals, 81, point, 3
标准差的计算是将每一个数值与平均值的差进行平方后,对该平方值再求平均数,然后再对其求平方根。
第一步是计算每个考分的偏差 (与平均值的差异),并对该偏差进行平方:
考分 | 偏差值 | 偏差值的平方 | ||
---|---|---|---|---|
85 | 85, minus, 81, point, 3, equals | 3, point, 7 | left parenthesis, 3, point, 7, right parenthesis, squared, equals | 13, point, 69 |
82 | 82, minus, 81, point, 3, equals | 0, point, 7 | left parenthesis, 0, point, 7, right parenthesis, squared, equals | 0, point, 49 |
88 | 88, minus, 81, point, 3, equals | 6, point, 7 | left parenthesis, 6, point, 7, right parenthesis, squared, equals | 44, point, 89 |
86 | 88, minus, 81, point, 3, equals | 4, point, 7 | left parenthesis, 4, point, 7, right parenthesis, squared, equals | 22, point, 09 |
85 | 85, minus, 81, point, 3, equals | 3, point, 7 | left parenthesis, 3, point, 7, right parenthesis, squared, equals | 13, point, 69 |
93 | 93, minus, 81, point, 3, equals | 11, point, 7 | left parenthesis, 11, point, 7, right parenthesis, squared, equals | 136, point, 89 |
98 | 98, minus, 81, point, 3, equals | 16, point, 7 | left parenthesis, 16, point, 7, right parenthesis, squared, equals | 278, point, 89 |
40 | 40, minus, 81, point, 3, equals | minus, 41, point, 3 | left parenthesis, minus, 41, point, 3, right parenthesis, squared, equals | 1705, point, 69 |
73 | 73, minus, 81, point, 3, equals | minus, 8, point, 3 | left parenthesis, 8, point, 3, right parenthesis, squared, equals | 68, point, 89 |
83 | 83, minus, 81, point, 3, equals | 1, point, 7 | left parenthesis, 1, point, 7, right parenthesis, squared, equals | 2, point, 89 |
然后我们计算平方偏差的平均值,也就是常说的方差。上面表格中,用最后一列数字之和除以行数:
方差 = 2288, point, 1, slash, 10 = 228, point, 81
最后,通过对方差开方求平方根,就得到了标准差。
标准差 = square root of, 228, point, 81, end square root = 15, point, 13。
想要学习更多关于标准差的内容?点击这里可以在可汗学院里深入学习 方差和标准差 。
幸运的是,要在这里的程序中使用随机数的正态分布,我们自己不必做任何这些计算。我们可以使用 ProcessingJS 提供的
Random
对象。要使用
Random
函数,首先要将一个新的 Random
对象示例化,并将 1 作为参数传入。我们将这个变量称为 "生成器" ,因为我们创建的这个函数基本上可以被看做是一个随机数字生成器。var generator = new Random(1);
如果我们想在每次运行
draw()
时,就生成一个符合正态分布 (或高斯分布)的随机数,这其实就像调用函数 nextGaussian()
一样简单。var num = generator.nextGaussian();
println(num);
现在我们应该如何处理这个值呢?例如,如果我们想用它来分配我们在屏幕上绘制的形状的 x 轴位置,具体该怎么办?
使用
nextGaussian()
函数会返回正态分布的随机数,其参数如下: 平均值为零 并且 标准差为1 。假设我们想要一个平均值为 200(即宽度400像素窗口中的中心水平位置)和标准差为60像素的随机数。我们可以通过调整数值乘以标准差再加上平均值的方式来调整参数。var standardDeviation = 60;
var mean = 200;
var x = standardDeviation * num + mean;
现在,我们可以创建一个程序,根据正态分布绘制半透明的圆圈。颜色最暗的点位于圆中心附近,大部分数值都聚集在中心附近,但经常有向左或向右偏离的圆圈。
“自然模拟”系列课程是由 Daniel Shiffman 的 "编程的本质" 衍生而来,基于 知识共享归属-非商用 3.0 本地化许可协议。