用Python模拟高尔顿钉板实验

Posted 天元浪子

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了用Python模拟高尔顿钉板实验相关的知识,希望对你有一定的参考价值。

昨天刚刚在油管上看过弗朗西斯·高尔顿的故事,今天就在CSDN上见到有人提问如何用Python模拟高尔顿钉板实验。

提到高尔顿,人们总是把他和钉板实验联系在一起,偶尔也会有人提及他是达尔文的表弟。实际上,作为维多利亚时代的人类学家、统计学家、心理学家和遗传学家,同时又是热带探险家、地理学家、发明家、气象学家,高尔顿简直就是一位集大成者。

高尔顿钉板形如上图所示:木板上钉有锥形排列的多层钉子,每颗钉子的水平位置正好位于下一层的两颗钉子正中间;小球在下落的过程中碰到钉子之后,可能从左边滚落,也可能从右边滚落,概率都是1/2;穿过m-1层钉板后,小圆球最终会落入下方的m个容器的某一个中。

这个实验之所以有名,是因为实验结果服从正态分布。不过也有人说,高尔顿钉板的实验结果服从二项分布,只是二项分布的概率密度函数可以用正态分布近似而已,和正态分布没什么关系。我不懂数学,只好把两种说法都罗列在这里,供读者参考。

好了,明白了高尔顿钉板的原理,就该程序员一展身手了。先定义一个函数,实现小球穿过m-1层钉板后落到m个容器的某一个中,容器编号从0开始。

>>> import random
>>> def galton(m):
	pos = 0
	for i in range(1, m):
		if random.random() > 0.5:
			pos += 1
	return pos

>>> galton(9)
4
>>> galton(9)
5
>>> galton(9)
4
>>> galton(9)
4
>>> galton(9)
2

这样测试太慢了,我们干脆把测试次数n也传到函数中。

>>> def galton(m, n):
	result = [0 for i in range(m)]
	for i in range(n):
		pos = 0
		for j in range(1, m):
			if random.random() > 0.5:
				pos += 1
		result[pos] += 1
	return result

>>> galton(9, 100)
[0, 7, 13, 19, 30, 19, 10, 2, 0]

看起来的确很像正态分布的样子。我们不妨用matplotlib画出多条曲线看看,这次是14层钉板1000个小球,测试3次。

>>> import matplotlib.pyplot as plt
>>> for i in range(3):
	plt.plot(galton(15, 1000))

	
[<matplotlib.lines.Line2D object at 0x0000020938174D88>]
[<matplotlib.lines.Line2D object at 0x000002093817FF08>]
[<matplotlib.lines.Line2D object at 0x0000020938185708>]
>>> plt.show()

结果如下图所示。实验完成。

以上是关于用Python模拟高尔顿钉板实验的主要内容,如果未能解决你的问题,请参考以下文章

高尔顿钉板仿真模拟 MATLAB

高尔顿钉板与二项分布

正态分布的期望和方差

高尔夫模拟器投影仪的最佳位置我来答

代码高尔夫:Mandelbrot 套装

抽卡程序模拟