这是一本数学书还是一本编程书?学好数学,让你成为更好的程序员

《计算思维与Python编程》是我们早期的Mathematics for the Digital Age and Programming in Python一书的 “更早讲Python”的版本。在本书中,我们更早地介绍了Python特性,为读者提供了必要的工具,使读者可以更快地以更加“Python式(pythonic)”的惯用方式,开始编写Python代码。在本书中,我们增加了两章(“第9章 海龟绘图”和“第14章 向量和矩阵”),以及介绍斐波那契数列的一节(“第10章 序列与和”的10.5节);更新了许多示例、练习和解答;更改了标题,从而更好地匹配这一系列主题和快速变化的技术环境与词汇。

但《计算思维与Python编程》的主要理念仍然没有改变:介绍离散数学概念和思维,我们认为这些概念是所有有基础的编程人员的基本知识。这种数学知识很容易学习,但美国大多数中小学数学课程还没有包括离散数学的内容。本书的数学部分包括许多动手编程练习,这些练习可以强化学生对编程和数学的认识。

“那么,这是一本数学书还是一本计算机编程书?”这可能是心急的读者心中的第一个问题。但为什么必须选择呢?这是图书管理员的困境:“它是属于数学类还是计算机类?”有一个简单的解决方案:在每类书架上各放一本。

本书的目的是教授一种特定的思维方式——精确思维,以及如何解决需要这种思维方式的问题。数学和计算机编程都能培养精确思维的能力,并解决那些需要精确解的问题。

数学教会我们欣赏严谨论证的美。从长远来看,这比解决当前实际问题的课程更有价值。数学并不是存在于真空中的——它的抽象植根于几个世纪以来积累的实践知识。数学教学借鉴了我们周围世界的例子和类比,至少它应该如此。然而,我们周围的世界变化得越来越快。在过去的五六十年间,我们的世界变得数字化了。这种变化如此深刻,以至于人们有时难以完全理解。我们的中小学数学课程在很大程度上忽略了这种变化,这是否就是人们难以理解这种变化的原因?

如果我们能够造出“时间机器”,让欧几里得穿越时空来到现代化的世界,他会觉得很欣慰,因为在现代技术的浪潮中,他熟悉的几何学仍然在学校里教授。“老对手”牛顿和莱布尼茨都会感到非常满意,因为成千上万的美国高二和高三学生正在学习如何求导和使用积分。但是,离现在不远的乔治·布尔(George Boole),尽管他的名字在每一种现代计算机编程语言中都是不朽的,但他仍然需要搜寻几十本教材才能找到他提出的代数。至于约翰·冯·诺依曼(John von Neumann),这位才华横溢的数学家,也是计算机技术的先驱之一……好吧,按照他一贯的乐观态度,他会预测在20年左右的时间里,每个小学生都会学习与门、或门和非门。但是,为什么事实不是如此呢?

在《计算思维与Python编程》中,我们汇集了一些与数字世界相关的更容易理解的数学主题。其中许多主题,通常在大学新生课程中以“离散数学”之名讲授。离散数学已成为所有基础数学的代名词,但在标准的初中和高中代数、微积分初步和微积分课程中,这种数学都被忽略了。在20世纪70年代,唐纳德·克努特(Donald Knuth)和他在斯坦福大学的同事创造了“具体数学”这一名词(融合了连续数学和离散数学,并且也很具体,不是太抽象),来描述克努特在斯坦福大学教授的课程。后来,“具体数学”成为了他们的一本阅读起来很愉快的书的标题[1]。正如他们在序言中解释的那样,克努特“发现他的技能中缺少一些数学工具,他需要一些数学工具,以便对计算机程序有彻底的、充分的理解,这些数学工具与他在大学里作为数学专业学生所学的东西完全不同”。

因此,如果你对计算机编程感兴趣,我们希望本书能让你成为更好的计算机程序员。如果你对数学更感兴趣,你将有充分的机会解决有趣的问题,并在计算机程序中,对其中的一些问题进行建模。你将熟悉通常初中生和高中生不会接触到的有趣的数学;你将学会解决真实问题(即你事先并不知道如何解决的问题);你将感受到数学推理和证明的力量。作为奖励,你将获得Python(一种流行的经济有效的编程语言)编程的实用技能。

我们选择Python有几个原因。首先,Python让你有机会在交互式环境中,通过即时反馈来体验该语言。其次,Python的语法并不太复杂。再次,Python具有简单但强大的功能,可用于处理列表和“字典”(映射)。最后,Python易于安装和使用,它是免费的。当然,还有其他编程语言具有类似的属性,可以满足我们的需求。归根结底,重要的不是特定的编程语言,而是能够精确地思考数学知识和计算机程序。

这是一本数学书还是一本编程书?学好数学,让你成为更好的程序员_第1张图片

 

  • 这本书在美国高中和大学的相关课程中都获得了巨大成功;
  • 本书文字优美、引人入胜;

教授基本的Python编程技能,并提高读者的计算思维能力和数学水平。 
我曾经这样告诉校长:"通常,我们很难去夸奖教材,但这本书的确是一本出色的教材"。 
——Michel Paul,美国比佛利山庄高中 
我一般不会写评论,但是这本书值得!实际上,阅读这本书,你可以学习数学和Python编程的方方面面,这在学习更高水平的Python编程时将非常有用。我是一名新手程序员,迫切需要这样一本书! 
——Willis Cook,读者 
这是一本精彩的图书,阐释了包括数论在内的丰富的数学知识。高中生就能够理解这些内容,并完成书中的编程示例和问题。 
——Earl J. Strassberger,美国芝加哥公立学校

样章试读:第13章 概率

13.1 引言

当我们掷一对骰子时,得到11点的可能性是多少?7点或11点,哪个更有可能?如果我们掷一对骰子100次,我们大概会得到多少次11点?概率论可以帮助回答这些问题。

事件的概率是介于0和1之间的数字,用于描述当我们多次重复实验时发生该事件的可能性。0意味着事件永远不会发生,1表示事件总是发生,0.5表示事件大约在一半情况下发生。

要询问和回答有关概率的问题,我们首先需要正式描述事件是什么,然后我们可以找出一种计算事件概率的方法。

假设我们有一个实验产生一些结果(一个数字、一个事物或一个特定的事物组合)。所有可能结果的集合称为实验的“概率空间”。在本书中,我们仅处理具有有限数量的可能结果的实验。换句话说,概率空间是有限集。例如,当我们掷出表面上有1、2、3、4、5和6点的骰子时,有6种可能的结果,因此概率空间是一组6个元素的集合,{1, 2, 3, 4 , 5, 6}。

“事件”被定义为概率空间的子集,它由满足特定标准的所有“有利”结果组成。我们可以定义以下事件:骰子上的点数为3或更大。此事件可以描述为集合{3, 4, 5, 6}。事件的其他例子:骰子上的点数是偶数,{2, 4, 6};点数是6,{6}。在后一个例子中,事件是仅有一个元素的概率空间的子集。

13.2 通过计数计算概率

如果概率空间中的所有结果可能性相等,事件的概率被定义为有利结果的数量与所有可能结果的数量的比值。

这是一本数学书还是一本编程书?学好数学,让你成为更好的程序员

 

 

例1

当我们掷出表面上有1、2、3、4、5和6点的骰子时,获得3点或更大点的概率是多少?

有6种可能的结果,6种结果的可能性都是相等的。其中4种结果点数为3或以上,即{3, 4, 5, 6}。因此,获得3点或更大点的概率是

这是一本数学书还是一本编程书?学好数学,让你成为更好的程序员

 

=

这是一本数学书还是一本编程书?学好数学,让你成为更好的程序员

 

✦ ✦ ✦

当我们掷一对骰子时,情况稍微复杂一些。这种情况下我们如何定义概率空间?第一个骰子和第二个骰子上的任何点组合都是不同的结果。那么概率空间将由36个元素组成(见图13-1)。同样,36种不同结果中的每一种的可能性都是相等的。

这是一本数学书还是一本编程书?学好数学,让你成为更好的程序员_第2张图片

 

图13-1 掷出两个骰子的可能结果的概率空间有36个元素,第一个和第二个骰子上所有可能的点的组合

例2

当我们掷一对骰子时,骰子上的点总和是11的概率是多少?总和是7的概率是多少?

得到11的概率可以计算为2/36 = 1/18,因为正好有2个可能的结果产生总和11点,即5 + 6和6 + 5。得到7的概率是6/36 = 1/6,因为有6个可能的结果得到总和7点1 + 6、2 + 5、3 + 4、4 + 3、5 + 2和6 + 1(见图13-2)。

✦ ✦ ✦

当整个概率空间被分成几个非重叠事件时,这些事件的概率和总是1。

图13-2展示了一个例子。

这是一本数学书还是一本编程书?学好数学,让你成为更好的程序员_第3张图片

 

图13-2 在一对骰子上获得一定点数的概率

你可能想知道:如果我们对两个骰子上的点数之和感兴趣,为什么不选择一个只包含11个元素的简单概率空间,可能的总和为2,3,…,12?从技术上讲,我们可以这么做,但这样的概率空间不会非常有用。因为正如我们所看到的,这个概率空间中的不同结果具有不同的概率。这个概率空间无助于我们计算每个结果的概率,也无法计算各种其他事件的概率。

当我们为问题构造概率空间时,总是尝试选择一个所有结果具有相同概率的空间。

在所有结果具有相同概率的空间中,每个结果的概率是1/n,其中n是所有可能结果的数量。然后,我们可以简单地计数满足事件标准的结果数量,并将该计数除以n,从而求出事件的概率。

✦ ✦ ✦

有时我们可以针对相同的情况,以不同的方式定义概率空间,但对于相同事件的概率,我们应该得到相同的结果。

例3

如果我们从52张牌中随机抽出2张牌,抽到2张A的概率是多少?

我们可以将概率空间定义为所有牌对的集合(忽略牌对中两张牌的顺序)。有

这是一本数学书还是一本编程书?学好数学,让你成为更好的程序员

 

种方法可以从52张牌中选择一对牌。有

这是一本数学书还是一本编程书?学好数学,让你成为更好的程序员

 

种方法可以从4个A中选择一对A(有利的结果)。答案是

这是一本数学书还是一本编程书?学好数学,让你成为更好的程序员

 

另解:我们可以将概率空间定义为所有有序牌对的集合。这个空间中的元素数量是

这是一本数学书还是一本编程书?学好数学,让你成为更好的程序员

 

,有序的A对的数量是

这是一本数学书还是一本编程书?学好数学,让你成为更好的程序员

 

。我们得到了同样的答案:

这是一本数学书还是一本编程书?学好数学,让你成为更好的程序员

 

例4

如果我们抛3次硬币,那么出现刚好2次正面朝上的概率是多少?

这里的概率空间是{HHH, HHT, HTH, HTT, THH, THT, TTH, TTT},期望的结果是{HHT, HTH, THH}。答案是3/8。

第13.2节练习

1.如果随机猜测5个答案选项的多项选择题,猜中正确答案的概率是多少? ✔

2.如果你掷2个骰子,那么点数的总和大于7的概率是多少?

3.你必须在36个方格的网格上标记正确的6个方格。你标记正确的概率是多少?✔

4.如果你抛硬币5次,出现至少4次反面的概率是多少?

5.轮盘中有36个槽的编号为1~36,另有2个槽,标记为0,表示对于获胜。36个槽18个红色和18个黑色交替,0是绿色。如果你选择17号槽,获胜的概率是多少?如果你选择“红色”,获胜的概率是多少(如果球击中任何红色位置你就赢了)? ✔

6.从前50个正整数中随机选择的数字,被3整除的概率是多少?

7.随机选择两位正整数(即10到99之间的整数),两个数字相同的概率是多少?

8.■编写一个Python程序,计算在掷3个骰子时获得不同点数总和(3~18)的概率。什么点数总和出现概率最高? »提示:初始化一个计数列表,全部设置为0,然后在三个骰子上生成所有可能的点组合,并为每个组合增加适当的计数。«

13.3 更多通过计数的概率

我们知道,要计算事件的概率,必须计算所有“有利”结果的数量,并将它除以所有可能结果的数量。当我们进行计数时,可以回顾在第12章的组合学问题中学到的所有技巧。

例1

如果5张牌是从52张牌中随机发出的,获得“两对”的概率是多少(即一对牌有一样的牌面数字,另一对牌有一样的牌面数字,剩下那张牌有不一样的牌面数字)?

发5张牌的方法总数是

这是一本数学书还是一本编程书?学好数学,让你成为更好的程序员

 

。为了形成“两对”,让我们首先从13种牌面大小中选择2种作为对子,有

这是一本数学书还是一本编程书?学好数学,让你成为更好的程序员

 

种办法。对于每一种牌面数字,有6种方法可以从4张牌中选择2张。最后有44种方法可以选择剩下的牌(从剩下的11种牌面数字选择)。答案是

这是一本数学书还是一本编程书?学好数学,让你成为更好的程序员

 

例2

袋中有60个果冻豆,其中,15个是红色,15个是蓝色,15个是绿色,15个是黄色。丹尼已经拿出1个红色的果冻豆和1个蓝色的果冻豆,袋子里还剩58个果冻豆。如果丹尼随机再拿出3个果冻豆,他最终得到3个颜色相同的果冻豆的概率是多少?

我们将使用计数的加法和乘法规则。对于有利的结果,有4种相互排斥的可能性:丹尼最终会得到3个红色、3个蓝色、3个绿色或3个黄色的果冻豆。要得到3个红色的果冻豆,他需要选择袋子里剩下的14个红色果冻豆中的2个,有

这是一本数学书还是一本编程书?学好数学,让你成为更好的程序员

 

种办法。然后他需要再选择一个不是红色的果冻豆,有

这是一本数学书还是一本编程书?学好数学,让你成为更好的程序员

 

种办法。因此,有

这是一本数学书还是一本编程书?学好数学,让你成为更好的程序员

 

种方法拿5个果冻豆,其中3个是红色。拿出3个蓝色果冻豆的方法总数相同。要获得3个绿色果冻豆,丹尼需要在15个绿色果冻豆中选择3个,有

这是一本数学书还是一本编程书?学好数学,让你成为更好的程序员

 

种方法。同样,有455种方法可以选择3个黄色果冻豆。有利结果的总数是4004 + 4004 + 455 + 455 = 8918。所有可能结果的总数是从58个果冻豆中选择3个果冻豆的方法的数量,即

这是一本数学书还是一本编程书?学好数学,让你成为更好的程序员

 

。获得3个相同颜色的果冻豆的概率是

这是一本数学书还是一本编程书?学好数学,让你成为更好的程序员

 

✦ ✦ ✦

当我们将概率计算为有利结果的数量与所有可能结果的数量的比率时,概率空间中的所有可能结果具有相等的概率是非常重要的。如果不是这样,那么简单比率方法将导致答案错误。

例3

考虑两个玩家之间的游戏。每个玩家最多掷3次硬币,谁先获得正面谁胜。如果他们第一次得到硬币的同一面,就会进行一个决胜局;如果再次得到相同的一面,他们会进行另一个决胜局。第一个玩家获胜的概率是多少?

这是一本数学书还是一本编程书?学好数学,让你成为更好的程序员_第4张图片

 

在一个不成熟的方法中,我们会考虑所有可能的游戏过程:

有7种可能的方式玩家A会赢,有7种可能的方式玩家B会赢。游戏有8种可能的方式以平局结束。

似乎玩家A获胜的概率是

这是一本数学书还是一本编程书?学好数学,让你成为更好的程序员

 

。答案错误!上面列出的22种可能的游戏过程,不是等可能的。为了看到这一点,让我们允许每个玩家掷3次,无论发生何种情况,最后才决定胜利者。

这是一本数学书还是一本编程书?学好数学,让你成为更好的程序员_第5张图片

 

这里*是一个通配符,可以代表硬币的任何一面。这个新的概率空间定义恰当,所有结果都是等可能的,旧的概率空间没有这个属性。正如我们现在所看到的,H/T游戏的获胜概率实际上是HH/HT的游戏的4倍,是HHH/HHT游戏的16倍。

新概率空间可能的结果总数是

这是一本数学书还是一本编程书?学好数学,让你成为更好的程序员

 

,正确的答案是

这是一本数学书还是一本编程书?学好数学,让你成为更好的程序员

 

在这个例子中,我们不必计算所有获胜组合数。根据玩家的对称性,有一个快捷方法:结果总数是

这是一本数学书还是一本编程书?学好数学,让你成为更好的程序员

 

,平局游戏结果的数量是

这是一本数学书还是一本编程书?学好数学,让你成为更好的程序员

 

,所以玩家A获胜的结果数量是

这是一本数学书还是一本编程书?学好数学,让你成为更好的程序员

 

第13.3节练习

1.在一副牌(52张)中获得“4张同点”扑克牌的概率是多少(同一牌面大小的4张牌加上任意第五张牌)?✔

2.■“皇家同花顺”是最好的牌,即同一花色的A、K、Q、J和10。当你从一套标准的52张牌中随机发出5张牌时,获得皇家同花顺的概率是多少?✔

3.■在“十点”基诺游戏中,你在一张有80个数字的卡片上标记10个“点”(数字),然后对手随机挑选20个数字。要赢得胜利,你需要让10个数字全被对手数字“击中”。赢得胜利的概率是多少?(基诺游戏给玩家带来了所有游戏中最小的获胜概率。)✔

4.■一个袋子中有3个红色大理石和5个蓝色大理石。如果你随机抽出4个,得到2个红色和2个蓝色的概率是多少?

5.◆ 从52张牌中抽牌,直到得到2张牌面数字相同的牌。不超过3张牌就结束的概率是多少?✔

6.◆ 书中的页面编号为1到96。我们剪下所有页码并将它们剪成单独的数字,从中随机选择两个数字,它们的和为10的概率是多少?

7.◆ 将16个台球随机放入6个口袋中。(假设一个口袋可以容纳任意数量的球。)东北角口袋少于3个球的概率是多少? ✔

8.◆ 随机的21点的3张牌,值为21点的概率是多少?在21点中,每张数字牌按由2到10的面值计数;A算作1或11,你可以选择一种;其他“图片”牌(J、Q或K)计为10。 ✔

13.4 乘法、加法和减法

还记得我们如何使用乘法、加法和减法来计数吗?当然,在计算“有利”结果和实验的所有可能结果的数量时,我们可以应用这些方法。但有一条捷径:我们可以直接对概率应用乘法、加法和减法运算。让我们从乘法开始。

假设我们有两个相互独立的实验。假设事件A可以在第一个实验中发生,事件B可以在第二个实验中发生。A和B在各自实验中发生的概率是A的概率乘以B的概率。

例1

如果我们连续掷两次骰子,获得两个6的概率是多少?

第一次掷骰子得到6的概率是

这是一本数学书还是一本编程书?学好数学,让你成为更好的程序员

 

,第二次得到6的概率是

这是一本数学书还是一本编程书?学好数学,让你成为更好的程序员

 

。连续获得两个6的概率是

这是一本数学书还是一本编程书?学好数学,让你成为更好的程序员

 

。注意,掷两次骰子与同时掷两个一样的骰子相同。

例2

我有3个信封。其中两个有1美元,第3个是空的。你可以带走任意两个信封。你最终得到两美元的概率是多少?

拿第一个信封时,获得1美元的概率是

这是一本数学书还是一本编程书?学好数学,让你成为更好的程序员

 

。如果你得到第一个1美元,从剩下的两个信封获得第二个1美元的概率是

这是一本数学书还是一本编程书?学好数学,让你成为更好的程序员

 

。获得2美元的概率是

这是一本数学书还是一本编程书?学好数学,让你成为更好的程序员

 

。如果我们假设第一个实验在第二个实验之前是成功的,乘法规则仍然有效。这类似于计数组合而没有重复,正如我们在12.3节中讨论的那样。

✦ ✦ ✦

概率可以在两种情况下相乘:当事件彼此独立时,如上面的例1所示;当基于第一事件已经发生的假设成立计算第二事件的概率时 ,如上面的例2所示。

例3

在加勒比海的尼维斯岛上,平均每年降雨45天。连续两天下雨的概率是多少?

这是一个棘手的问题。你可能想应用乘法规则,并说概率是

这是一本数学书还是一本编程书?学好数学,让你成为更好的程序员

 

这是一本数学书还是一本编程书?学好数学,让你成为更好的程序员

 

。但是,乘法规则要求事件彼此独立地发生,天气情况不是这样,在尼维斯岛,雨季是9月和10月,在这两个月里连续两天降雨很有可能。为了论证这一问题,假设在某个神秘岛上,45个雨天总是在9月1日到10月15日之间,并且在一年中的其余时间里根本不会下雨。那么,如果我们随机选择一年中连续两天,则两天都会下雨的概率是

这是一本数学书还是一本编程书?学好数学,让你成为更好的程序员

 

。如果没有关于全年雨天分布的更多信息,我们无法回答最初关于尼维斯岛的问题。

✦ ✦ ✦

当我们需要找到可以分成两个无重叠事件的事件概率时,使用加法。

例4

在掷骰子的游戏中,你掷两个骰子。如果你掷到7或11,你就赢了;如果你掷到2、3或12,就输了;其他情况游戏继续。在第一次掷骰子上赢或输的概率是多少?

在第一次掷骰子时获胜的概率是

这是一本数学书还是一本编程书?学好数学,让你成为更好的程序员

 

(见图13-2);在第一次掷骰子时失败的概率是

这是一本数学书还是一本编程书?学好数学,让你成为更好的程序员

 

。(但这不是游戏的结束,获胜规则是这样的:最终在游戏中赢得超过一半的比赛。)

例5

在“随机行走”中,你可以随机选择下一步行走的方向(前进、后退、左或右),它们具有相同的概率。两步后返回起始位置的概率是多少?

有以下4个序列在两步后可返回起始位置,{前,后}、{后,前}、{左,右}和{右,左}。每个序列发生的概率是

这是一本数学书还是一本编程书?学好数学,让你成为更好的程序员

 

。4个序列中的任何一个发生的概率是

这是一本数学书还是一本编程书?学好数学,让你成为更好的程序员

 

✦ ✦ ✦

如果事件发生的概率为p,则不发生同一事件的概率为1−p。

例6

戴夫击出本垒打的概率是0.13。戴夫不会击出本垒打的概率是多少?

这是一本数学书还是一本编程书?学好数学,让你成为更好的程序员

 

例7

艾米莉平均每15次用飞镖击中“靶心”1次。艾米莉在3次尝试中至少会击中靶心1次的概率是多少?

假设艾米莉击中靶心的概率为p,错过靶心的概率是

这是一本数学书还是一本编程书?学好数学,让你成为更好的程序员

 

。则艾米莉连续3次错过靶心的概率是

这是一本数学书还是一本编程书?学好数学,让你成为更好的程序员

 

,3次尝试中至少1次击中靶心的概率是

这是一本数学书还是一本编程书?学好数学,让你成为更好的程序员

 

。这里

这是一本数学书还是一本编程书?学好数学,让你成为更好的程序员

 

。答案是

这是一本数学书还是一本编程书?学好数学,让你成为更好的程序员

 

第13.4节练习

1.连续3次掷骰子都得到3的概率是多少? ✔

2.在Scrabble中,有98个写有字母的方块。有2个B、9个A和6个T。如果你从盒子中随机拿出3个方块,每次将方块放回到盒子中,按顺序获得B、A、T的概率是多少?

3.掷3次骰子而从未得到6的概率是多少?至少得到一次6的概率是多少? ✔

4.■ 如例5所述,在随机行走时,你在4步后返回起始位置的概率是多少?

5.■在壁球比赛中,一连串连续的击球被称为1个回合。当你发球时,要得分,你需要赢得该回合。如果你的对手发球,赢得1个回合只是给你下一个发球的权利。如果艾莉在她发球时,平均赢得10个回合中的4个;在她的对手发球时,赢得10个回合中的3个。那么从对手发球开始,2回合后,艾莉得一分(一球一分)的概率是多少? ✔

6.◆ 练习题5描述了壁球得分的规则。不管是谁发球,苏珊平均在3个回合中有2个回合击败吉米。如果苏珊开始发球,她在3个回合中赢得下一分的概率是多少?在5个回合中苏珊最终会赢得下一分的概率是多少? »提示:在情况下,我们得到一个无穷极数,但我们已经知道如何处理它……« ✔

7.◆ 如果选手发球,并且选手的对手和选手水平相当(也就是说,每个选手赢得一个回合的概率是0.5,无论谁发球),那么选手在壁球中赢得下一分的概率是多少(参见练习题6)?

8.◆ 一个飞镖靶有20个外部扇区,20个内部扇区和一个叫“靶心”的中心。如果平均而言,在30次尝试中击中靶心一次,内部扇区5次(在它们中间等可能),外部扇区20次,完全错过了4次。那么连续两次击中同一扇区(或靶心)的概率是多少?✔

9.◆ 在某抽奖活动中,你可以从42个数字中选择6个数字。如果你的数字与计算机抽出的数字相匹配,那么你将获得累积奖金。计算机还抽出第七个“鼓励”数字。如果你没有中奖,但是你的6个数字与电脑抽取的7个数字(包括鼓励数字)中的任意6个数字相匹配,你将获得10000美元的安慰鼓励奖。还有其他奖品,但它们相对较小。只有当你的“平均赢额”(中奖概率乘奖金的大小,加上安慰鼓励奖的概率乘以鼓励奖金的大小)超过票价时,你才决定玩游戏。如果一张票的价格为1.00美元,那么累积奖金达到多少才值得你玩?

10.◆ 一个棋子从棋盘左下角的黑色方格开始移动。在每次移动中,棋子以相同的概率向上或向右移动一个方格,它到达右边或顶边时停止。棋子最后在黑色方格上的概率是多少? »提示:扩展棋盘,使它形成一个等边直角三角形,直角在左下角,并将所有路径延伸到它的斜边,使所有路径的长度相等。«

13.5 伪随机数

计算机应该是可预测的,从相同的位置开始,执行相同的步骤,你应该得到相同的结果。但有时我们希望计算机随机行动。例如,在游戏和随机过程的计算机模拟中,随机行动是有用的。

典型的编程语言具有生成“随机”数字的库函数。这些数字是利用某种算法在软件中生成的,因此它们并非真正随机,但它们近似于随机行为。这些数字称为“伪随机数”。

Python库有一个random模块,它有许多生成和返回随机数的函数。要获取随机整数r,a

这是一本数学书还是一本编程书?学好数学,让你成为更好的程序员

 

r

这是一本数学书还是一本编程书?学好数学,让你成为更好的程序员

 

b,请将函数randint导入random模块,并调用randint(a, b)。例如:

>>> from random import randint
>>> randint(1,3)
2
>>> randint(1,3)
3
>>> randint(1,3)
3
>>> randint(1,3)
1
>>> randint(1,3)
2

(你的显示可能会有所不同,因为randint会返回伪随机数。)

来自同一模块的random函数返回一个浮点型数x,0.0

这是一本数学书还是一本编程书?学好数学,让你成为更好的程序员

 

x<1.0。例如:

>>> from random import random
>>> random()
0.21503763019111777
>>> random()
0.80958843480468412

另一个choice函数从字符串(或元组、列表或任何其他“序列”中的元素)中选择随机字符并返回。例如:

>>> from random import choice
>>> choice('ABC')
'B'
>>> choice('ABC')
'A'
>>> choice('ABC')
'A'

shuffle函数以随机顺序重新排列列表的元素。例如:

>>> from random import shuffle
>>> lst = [1, 2, 3, 4, 5]
>>> shuffle(lst)
>>> lst
[5, 2, 3, 1, 4]

✦ ✦ ✦

有时,理论上的解决方案为我们提供了一个公式,但数字可能太大或难以计算。于是,计算机可以提供帮助,通过计算或对随机过程建模并观察结果。这种模型被称为“蒙特卡罗模拟”。

在25人中,更有可能的是有两个人同一天生日,还是每个人的生日在不同的一天?

我们假设一个生日可以是365天中的任何一天(忽略闰年)。一种方法是通过编程进行蒙特卡罗模拟,生成一组随机的25个生日,并检查是否有两个生日在同一天。比方说,重复10,000次,并计数有多少组有两人同一天生日,有多少组没有。这个程序留给你作为练习(见练习题6)。

解决生日问题的另一种方法是使用我们学到的知识,在理论上计算概率。第一个人的生日可以是365天中的任意一天,第二个人也是,依此类推。利用乘法规则,我们发现有36525种生日的可能排列。利用没有重复的乘法规则,我们得出结论,当所有25个人生日都不同时,有

这是一本数学书还是一本编程书?学好数学,让你成为更好的程序员

 

种排列。因此,所有人生日不同的概率是

这是一本数学书还是一本编程书?学好数学,让你成为更好的程序员

 

,而至少两个人生日相同的概率是

这是一本数学书还是一本编程书?学好数学,让你成为更好的程序员

 

现在让我们针对n个人的情况解决同样的问题。不需额外的工作,我们就能够得到“交叉点”:当概率大于1/2时的人数。请尝试猜测这个数字,这只是为了检查一下你的直觉!

似乎我们必须处理分子和分母非常大的数字。例如,36525有65位数字。(我们用Python发现了这个数字。)Python支持大整数,其中一个数字可以有任意长度,仅受计算机内存大小的限制。当常规的4字节int值超出范围时,Python会自动切换到使用更长的值。所以在Python中,我们可以直接计算分数的分子和分母,取其比值并完成。然而,在其他语言中,处理非常大的数字可能涉及更多工作。幸运的是,我们可以更简便地处理这个问题,不用大整数。请注意,我们可以将比率分成单个分数的乘积:

这是一本数学书还是一本编程书?学好数学,让你成为更好的程序员

 

。这样很容易将每个分数计算为一个浮点型数据。在练习题5中,你将完成这个程序。

第13.5节练习

1.编写并测试一个Python函数,该函数从52张牌中随机选择5张牌。每张牌由一对数据(一个元组)描述,保存牌的花色(“S”“H”“D”“C”表示黑桃、红桃、方块、草花)和牌面数字(1到13)。 ✔

2.假设你有一个Python函数random_letter,它返回字母表的一个随机字母(26个字母的概率大致相等)。random_letter连续返回3个元音字母(AEIOU)的概率是多少? ✔

3.编写一个Python函数random_letter,如练习题2所述。运行3次以查看是否得到连续3个元音。重复100,000次,统计连续3个元音的次数,并估计这种事件发生的概率。将你的结果与你在练习题2中获得的理论概率进行比较。

4.编写一个使用蒙特卡罗方法估算 的程序。将一百万个随机(虚拟)点“投掷”到一个单位正方形中,并计数它们与原点的距离小于1的点的数量。

这是一本数学书还是一本编程书?学好数学,让你成为更好的程序员_第6张图片

 

5.■ 使用本节中描述的理论方法,编写一个程序,输出n个人中至少有两个人具有相同生日的概率,n取值为1到50,不使用太大的整数。这个程序只有几行代码。输出应如下所示:

 1: 0.000
 2: 0.003
 3: 0.008

...

48: 0.961
49: 0.966
50: 0.970

注意“OBOBs”(off-by-one bugs,差1错误),当程序中的循环运行少一次或多一次时,我们就说发生了这种错误。根据输出结果确定,概率大于0.5的n的值。

6.■编写一个程序,实现蒙特卡罗模拟。编写一个生成n个随机生日列表的函数(数字从1到365),如果列表中的所有数字都不同,则返回True。尽量多地调用此函数,以计算n中至少有两个人具有相同生日的概率。将你的结果与练习题5中获得的理论结果进行比较。 »提示:找出生成的数字是否有重复的简单方法是,分配365个计数变量,并针对每个随机数递增适当的计数变量,然后检查是否有任何计数变量大于1。«

7.■在海龟绘图中,绘制一个以原点为中心的半径为100的圆,然后将海龟归回原点(到原点)。模拟随机行走,在每次移动中,将海龟的方向设置为0度、90度、180度或270度,以相等的概率随机选择,然后向前移动20。保持笔落下以查看海龟的路径,计算并报告海龟离开圆圈所需的步数。 »提示:turtle的函数distance (x,y)返回从当前海龟位置到点(x, y)的距离。«

8.■下面的函数从序列s中返回一个随机的正数:

def positive_choice(s):
    lst = [x for x in s if x > 0]
    if len(lst) > 0:
        return choice(lst)

列表中的每个正数有相同的概率被选中。重写此函数,不从s创建任何临时正数列表或集合,也不提前计算它们的数量。 »提示:假设r保存从s的前k个正数中随机选择的一个正数,从k = 0和r = None开始。当你取得下一个正数x时,你可以保持r不变或用x替换r。用x替换r的概率应该是多少?(你永远不会知道:x可能是s中的最后一个正数。你需要给它一个公平的机会……)«

在(−1, 1, 2, 0, 3, −2, 4, 5, −6)上运行你的positive_choice函数,比方说10000次,从而测试它,并计算每个数字1、2、3、4、5的返回次数。所有数字的返回次数应该在2000左右,计数与2000的差距不大于120。 ✔

9.■本题探讨将多个随机数加在一起时会发生什么。写一个简短的程序,帮助你做到这一点。创建一个包含100个计数器的列表:counters = 100*[0]。运行以下程序:取100个随机数r,0

这是一本数学书还是一本编程书?学好数学,让你成为更好的程序员

 

r<1(由random函数返回)的总和,将和截断为整数,得到i,并递增计数器counters[i]。重复这些步骤,比如重复2000次。然后在计数器中将值显示为海龟绘图中的垂直线段(一种简单的条形图)。生成的图是什么样的?

»提示:

for i in range(100):
    x = x_offset + x_scale*i
    y = y_scale*counters[i]
    ...

使用合理的偏移量和缩放比:

x_offset, y_offset = -200, -100
x_scale, y_scale = 5, 1

使用goto(x, y)绘制。

13.6 复习

本章介绍的术语。

概率

概率空间

独立事件

概率的乘法规则

概率的加法和减法规则

蒙特卡罗模拟

随机行走

本章介绍的一些Python特性。

from random import randint, random, choice, shuffle
randint(m, n)
random()
choice(s)
shuffle(lst)

你可能感兴趣的:(程序员,离散数学,Python)