Python程序设计 课件 第9章 模拟与设计_第1页
Python程序设计 课件 第9章 模拟与设计_第2页
Python程序设计 课件 第9章 模拟与设计_第3页
Python程序设计 课件 第9章 模拟与设计_第4页
Python程序设计 课件 第9章 模拟与设计_第5页
已阅读5页,还剩81页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

模拟与设计第九章课程目标课程目标1理解模拟的应用可能是解决现实问题的一种方式324理解伪随机数及其在蒙特卡罗模拟中的应用理解并能应用自顶向下和螺旋式设计技术来编写复杂的程序理解单元测试,并能将这种技术应用于复杂程序的实现和调试PART1模拟短柄壁球1模拟短柄壁球解决现实问题的一个特别强大的技术就是“模拟”。开发一个短柄壁球比赛的简单模拟。PART2一个模拟问题2一个模拟问题Denny酷爱打短柄壁球,但是这几年来,他经常与那些比他好一点点的球员竞争,期间他大多数是被击败的,这让他很困扰。他觉得如果别人只是比他好一点点他应该不会输这么多。或许是他对自己的实力评价过高,又或许是对别人的实力评价过低。又或者是游戏本身的性质,能力上的小差异会导致球场上的不平衡比赛。编一个计算机程序来模拟短柄壁球的某些方面。PART3分析和规格说明3分析和规格说明短柄壁球是在两名球员之间使用球拍在四壁球场上打球的运动。3分析和规格说明比赛开始时,一名选手将球击出:这被称为“发球”选手交替击球,使其保持比赛状态,这是一个“回合”当其中一名选手未能有效击球时,对打结束输家是发球选手,则发球权转给另一名选手发球选手赢得了这一回合,则会得1分选手只能在自己发球时得分,第一名得到15分的选手赢得比赛。击球失误的选手输掉这一回合3分析和规格说明在模拟中,选手的能力水平将由选手在发球时赢得回合的概率来表示。程序将打印结果摘要将提示用户输入两名选手的发球回合得分概率用这些概率模拟多局短柄壁球比赛3分析和规格说明输入:该程序先提示并获取两名选手(称为“选手A”和“选手B”)的发球回合得分概率。然后程序提示并获取要模拟的比赛局数。输出:该程序将提供一系列的初始提示,如:A赢得比赛的概率是多少?B赢得比赛的概率是多少?一共模拟多少场比赛?3分析和规格说明游戏模拟:500A赢:268(53.6%)B赢:232(46.4%)注意:所有输入都被假定为合法的数值,不需要错误或有效性检查。在每次模拟比赛中,都是选手A先发球。PART4伪随机数4伪随机数伪随机数发生器从某个“种子”值开始工作。该值被送入一个函数以产生“随机”数字。下次需要一个随机数时,将当前值反馈到该函数中以产生一个新的数字。通过仔细选择的函数,得到的值序列基本上是随机的。一切都取决于生成函数和种子的值。4伪随机数Python提供了一个库模块,其中包含一些有用的函数来生成伪随机数。该模块中的函数根据模块加载的日期和时间推导出初始种子值,因此每次运行程序时都会获得不同的种子值。randrangerandom

重要函数4伪随机数>fromrandomimport*>>>randrange(1,6)2>>>randrange(1,6)1>>>randrange(1,6)1>>>randrange(5,105,5)20>>>randrange(5,105,5)70>>>randrange(5,105,5)70>>>randrange(5,105,5)75从给定范围中选择一个伪随机整数4伪随机数>>>fromrandomimport*>>>random()0.7635543105304049>>>random()0.31164370051447243>>>random()0.7039672847873445>>>random()0.5959989547801257用于生成伪随机浮点值4伪随机数假设选手的发球回合得分概率是0.70。if<playerwinsserve>:score=score+14伪随机数ifrandom()<prob:score=score+1假设生成一个0~1之间的随机值。区间(0,1)的70%正好在0.7的左边。所以70%的时间随机数将小于0.7,而其他30%的次数将大于等于0.7。一般来说,如果prob表示选手获胜的概率,则random()<prob就成功地表示了正确的概率。PART5自顶而下的设计5自顶而下的设计一种成熟的解决复杂问题的技术称为“自顶向下”。从总问题开始,尝试用较小的问题来表达解决方案问题变得很小,以至于它们可以轻松得到解决依次使用相同的技术,攻克每个较小的问题把所有的小块都拼回来,大功告成,得到一个程序PART6顶层设计6顶层设计打印介绍获取输入:probA,probB,n用probA和probB模拟n局短柄壁球比赛打印playerA和playerB的获胜报告输入处理输出遵循模式:6顶层设计打印介绍:defmain():printIntro()

6顶层设计从用户获取输入:probA,probB,n:defmain():printIntro()probA,probB,n=getInputs()6顶层设计用probA和probB模拟n局短柄壁球比赛:调用函数simNGames进行模拟比赛需要模拟的场n模拟使用怎样的probA和probB的值6顶层设计用probA和probB模拟n局短柄壁球比赛:defmain():printIntro()probA,probB,n=getInputs()winsA,winsB=simNGames(n,probA,probB)6顶层设计defmain():printIntro()probA,probB,n=getInputs()winsA,winsB=simNGames(n,probA,probB)printSummary(winsA,winsB)打印playerA和playerB的获胜报告:PART7关注点分离7关注点分离defmain():printIntro()probA,probB,n=getInputs()winsA,winsB=simNGames(n,probA,probB)printSummary(winsA,winsB)7关注点分离我们已经指定了执行这些任务的函数名称、参数和预期返回值。这些信息称为函数的“接口”或“签名”。唯一关注的是,如果给出比赛局数和两个概率,它必须返回每名选手获胜的正确局数。main函数只关心每个(子)函数“做什么”。7关注点分离图9.1短柄壁球模拟的一级结构图7关注点分离在设计的每个层次上,接口告诉我们下层的哪些细节很重要,其他东西都可以暂时忽略确定某些重要特征并忽略其他细节的一般过程称为“抽象”可以将自顶向下设计的整个过程视为发现有用抽象的系统方法PART8第二层设计第二课时defprintIntro():print("这个程序模拟了选手A和选手B之间的短柄垒球游戏,每个选手")

print("在发球阶段的得分可能性由一个概率(0和1之间的数字)来表示,")

print("总是选手A先发球。")8第二层设计8第二层设计defgetInputs():#返回三个参数probA,probB和na=float(input("A赢得发球的概率为多少?"))

b=float(input("B赢得发球的概率是多少?"))

n=int(input("一共模拟多少场比赛?"))

returna,b,n函数中的变量是该函数的局部变量。提示输入获取三个值,返回给主程序。PART9设计simNGames9设计simNGames初始化A和B的胜利场数为0循环n次模拟比赛如果A赢A的胜场叫1elseB的胜场加1基本思想是模拟n局比赛,并记录每名选手的胜利局数。defsimNGames(n,probA,probB):#模拟n次比赛返回winsA和winsBwinsA=0winsB=0foriinrange(n):9设计simNGames9设计simNGames下面模拟一句短柄垒球比赛。更新结构图以反映这些决定采用一个simOneGame函数来表示一场比赛以他们的成绩为输出,让simOneGame返回两名球员的最终成绩9设计simNGames图9.2短柄壁球模拟的二级结构图9设计simNGamesdefsimNGames(n,probA,probB):winsA=winsB=0foriinrange(n):scoreA,scoreB=simOneGame(probA,probB)ifscoreA>scoreB:winsA=winsA+1else:winsB=winsB+1returnwinsA,winsBPART10第三层设计10第三层设计对短柄壁球规则的逻辑进行编码:如何记录谁在发球呢?我要解决simOneGame问题!需要记录得分知道是谁在发球用存储“A”或“B”的字符串变量10第三层设计初始化scores为0选手"A"发球游戏没结束时一直循环:模拟任何一个正在发球的球员的发球更新游戏状态返回scores10第三层设计defsimOneGame(probA,probB):scoreA=0scoreB=0erving="A"while<condition>:10第三层设计只要比赛没结束,就需要继续循环这个条件到底是什么?将细节隐藏在另一个函数gameOver中,如果比赛结束,则返回True,否则返回False通过查看分数来判断游戏是否结束10第三层设计图9.3短柄壁球模拟的第三层结构图10第三层设计defsimOneGame(probA,probB):scoreA=0scoreB=0serving="A"whilenotgameOver(scoreA,scoreB):如果A在发球,那么我们需要使用A的概率,并且根据发球的结果,更新A的分数,或将发球更改为B。10第三层设计ifserving=="A":ifrandom()<probA:scoreA=scoreA+1else:serving="B"10第三层设计ifserving=="A":ifrandom()<probA:scoreA=scoreA+1else:serving="B"else:ifrandom()<probB:scoreB=scoreB+1else:serving="A"10第三层设计defsimOneGame(probA,probB):scoreA=0scoreB=0serving="A"whilenotgameOver(scoreA,scoreB):ifserving=="A":ifrandom()<probA:scoreA=scoreA+1else:serving="B"else:ifrandom()<probB:scoreB=scoreB+1else:serving="A"returnscoreA,scoreBPART11整理完成11整理完成defgameOver(a,b):#a和b表示一场壁球游戏的得分#如果游戏结束,则返回True,否则返回Falsereturna==15orb==1511整理完成fromrandomimportrandomdefmain():printIntro()probA,probB,n=getInputs()winsA,winsB=simNGames(n,probA,probB)printSummary(winsA,winsB)

defprintIntro():

print("这个程序模拟了选手A和选手B之间的短柄垒球游戏,每个选手")

print("在发球阶段的得分可能性由一个概率(0和1之间的数字)来表示,")

print("总是选手A先发球。")11整理完成defgetInputs():#返回三个参数probA,probB和na=float(input("A赢得发球的概率为多少?"))

b=float(input("B赢得发球的概率是多少?"))

n=int(input("一共模拟多少场比赛?"))

returna,b,n

defsimNGames(n,probA,probB):winsA=winsB=0foriinrange(n):scoreA,scoreB=simOneGame(probA,probB)ifscoreA>scoreB:winsA=winsA+1else:winsB=winsB+1returnwinsA,winsB11整理完成defsimOneGame(probA,probB):serving="A"scoreA=0scoreB=0whilenotgameOver(scoreA,scoreB):ifserving=="A":ifrandom()<probA:scoreA=scoreA+1else:serving="B"else:ifrandom()<probB:scoreB=scoreB+1else:serving="A"returnscoreA,scoreB11整理完成defgameOver(a,b):#a和b表示一场壁球游戏的得分

#如果游戏结束,则返回True,否则返回Falsereturna==15orb==15

defprintSummary(winsA,winsB):#打印选手的胜利场数即概率.

n=winsA+winsBprint("\n模拟游戏:",n)print("A赢:{0}({1:0.1%})".format(winsA,winsA/n))print("B赢:{0}({1:0.1%})".format(winsB,winsB/n))

if__name__=='__main__':main()PART12设计过程总结12设计过程总结自顶向下的设计实战:从结构图的最高层开始,一路向下。在每个层次上,我们从总算法开始,然后逐渐将它提炼为精确的代码。这种方法有时称为“逐步求精”。将算法表示为一系列较小的问题用较小问题的接口来表示该算法,从而描述算法的细节为每个小问题开发一个接口对每个较小的问题重复此过程PART13自底向上的实现13自底向上的实现当我们有一段完整代码时,即使我们再小心,但当我们测试验证时,还是有时可能会对结果有些失望。PART14单元测试14单元测试图9.4短柄壁球模拟的第三层结构图14单元测试>>>gameOver(0,0)False>>>gameOver(5,10)False>>>gameOver(15,3)True>>>gameOver(3,15)True14单元测试>>>simOneGame(.5,.5)(13,15)>>>simOneGame(.5,.5)(15,11)>>>simOneGame(.3,.3)(15,11)>>>simOneGame(.3,.3)(11,15)>>>simOneGame(.4,.9)(4,15)>>>simOneGame(.4,.9)(1,15)>>>simOneGame(.9,.4)(15,3)>>>simOneGame(.9,.4)(15,0)>>>simOneGame(.4,.6)(9,15)>>>simOneGame(.4,.6)(6,15)当概率相等时,分数接近。当概率相差较大时,比赛就是一边倒。14单元测试我们可以继续这样的部分实现,将组件添加到代码中,同时测试每个组件。软件工程师称这个过程为“单元测试”。独立测试每个函数更容易发现错误。当你测试整个程序的时候,有可能一切顺利。PART15模拟结果15模拟结果假设Denny赢球的概率为55%,比他强一点的选手赢球概率为60%,我们模拟1000次,运行结果如下:这个程序模拟了选手A和选手B之间的短柄垒球游戏,每个选手在发球阶段的得分可能性由一个概率(0和1之间的数字)来表示,总是选手A先发球。A赢得发球的概率为多少?0.55B赢得发球的概率是多少?0.6一共模拟多少场比赛?1000

模拟游戏:1000A赢:389(38.9%)B赢:611(61.1%)当相差很小时,Denny获胜的概率大概为三分之一。所以Denny输的不冤。PART16其他设计技术16其他设计技术自顶向下的设计是一种非常强大的程序设计技术,但并不是创建程序的唯一方法。PART17原型与螺旋式开发17原型与螺旋式开发另一种设计方法是从程序或程序组件的简单版本开始,然后尝试逐渐添加功能,直到满足完整的规格说明。初始的朴素版本称为“原型”。原型通常会导致一种“螺旋式”开发过程。设计、实现并测试一个原型新功能被设计、实现和测试在开发过程中,完成许多小循环,原型逐渐扩展为最终的程序17原型与螺旋式开发例:如何开发短柄壁球模拟。问题的本质在于模拟一个短柄壁球的比赛。我们可能就从simOneGame函数开始。进一步简化,的原型可以假设每名选手有一半对一半的机会赢得每一分,并且只比赛30回合。这需要考虑问题的关键,即处理得分和换发球。17原型与螺旋式开发fromrandomimportrandomdefsimOneGame():scoreA=0scoreB=0serving="A"foriinrange(30):ifserving=="A":ifrandom()<.5:scoreA=scoreA+1else:serving="B"else:ifrandom()<.5:scoreB=scoreB+1else:serving="A"print(scoreA,scoreB)

if__name__==’__main__’:simOneGame()17原型与螺旋式开发101020...777817原型与螺旋式开发初始原型。比赛30回合,发球者总是有50%的获胜机率。打印出每次发球后的分数。添加两个参数,表示两名选手的不同概率。比赛直到其中一名选手得到15分。此时,我们有了能工作的一局比赛的模拟。构建完整的程序。添加交互式输入和格式漂亮的结果报告。扩展进行多局比赛。输出是每名选手赢得的比赛数量。阶段1阶段3阶段4阶段2阶段5PART18设计的艺术18设计的艺术要注意的是,螺旋式开发不是自顶向下设计的替代品。相反,它们是互补的方法。在设计原型时,你仍然会使用自顶向下的技术。设计没有“唯一正确的方式”。事实上,良好的设计与科学一样是一个创造性的过程。事后可以对设计细致地分析,但是没有生成设计的硬性规则。课程目标小结

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论