Python程序設(shè)計 課件 第9章 模擬與設(shè)計_第1頁
Python程序設(shè)計 課件 第9章 模擬與設(shè)計_第2頁
Python程序設(shè)計 課件 第9章 模擬與設(shè)計_第3頁
Python程序設(shè)計 課件 第9章 模擬與設(shè)計_第4頁
Python程序設(shè)計 課件 第9章 模擬與設(shè)計_第5頁
已閱讀5頁,還剩81頁未讀 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

模擬與設(shè)計第九章課程目標(biāo)課程目標(biāo)1理解模擬的應(yīng)用可能是解決現(xiàn)實問題的一種方式324理解偽隨機數(shù)及其在蒙特卡羅模擬中的應(yīng)用理解并能應(yīng)用自頂向下和螺旋式設(shè)計技術(shù)來編寫復(fù)雜的程序理解單元測試,并能將這種技術(shù)應(yīng)用于復(fù)雜程序的實現(xiàn)和調(diào)試PART1模擬短柄壁球1模擬短柄壁球解決現(xiàn)實問題的一個特別強大的技術(shù)就是“模擬”。開發(fā)一個短柄壁球比賽的簡單模擬。PART2一個模擬問題2一個模擬問題Denny酷愛打短柄壁球,但是這幾年來,他經(jīng)常與那些比他好一點點的球員競爭,期間他大多數(shù)是被擊敗的,這讓他很困擾。他覺得如果別人只是比他好一點點他應(yīng)該不會輸這么多?;蛟S是他對自己的實力評價過高,又或許是對別人的實力評價過低。又或者是游戲本身的性質(zhì),能力上的小差異會導(dǎo)致球場上的不平衡比賽。編一個計算機程序來模擬短柄壁球的某些方面。PART3分析和規(guī)格說明3分析和規(guī)格說明短柄壁球是在兩名球員之間使用球拍在四壁球場上打球的運動。3分析和規(guī)格說明比賽開始時,一名選手將球擊出:這被稱為“發(fā)球”選手交替擊球,使其保持比賽狀態(tài),這是一個“回合”當(dāng)其中一名選手未能有效擊球時,對打結(jié)束輸家是發(fā)球選手,則發(fā)球權(quán)轉(zhuǎn)給另一名選手發(fā)球選手贏得了這一回合,則會得1分選手只能在自己發(fā)球時得分,第一名得到15分的選手贏得比賽。擊球失誤的選手輸?shù)暨@一回合3分析和規(guī)格說明在模擬中,選手的能力水平將由選手在發(fā)球時贏得回合的概率來表示。程序?qū)⒋蛴〗Y(jié)果摘要將提示用戶輸入兩名選手的發(fā)球回合得分概率用這些概率模擬多局短柄壁球比賽3分析和規(guī)格說明輸入:該程序先提示并獲取兩名選手(稱為“選手A”和“選手B”)的發(fā)球回合得分概率。然后程序提示并獲取要模擬的比賽局數(shù)。輸出:該程序?qū)⑻峁┮幌盗械某跏继崾?,如:A贏得比賽的概率是多少?B贏得比賽的概率是多少?一共模擬多少場比賽?3分析和規(guī)格說明游戲模擬:500A贏:268(53.6%)B贏:232(46.4%)注意:所有輸入都被假定為合法的數(shù)值,不需要錯誤或有效性檢查。在每次模擬比賽中,都是選手A先發(fā)球。PART4偽隨機數(shù)4偽隨機數(shù)偽隨機數(shù)發(fā)生器從某個“種子”值開始工作。該值被送入一個函數(shù)以產(chǎn)生“隨機”數(shù)字。下次需要一個隨機數(shù)時,將當(dāng)前值反饋到該函數(shù)中以產(chǎn)生一個新的數(shù)字。通過仔細選擇的函數(shù),得到的值序列基本上是隨機的。一切都取決于生成函數(shù)和種子的值。4偽隨機數(shù)Python提供了一個庫模塊,其中包含一些有用的函數(shù)來生成偽隨機數(shù)。該模塊中的函數(shù)根據(jù)模塊加載的日期和時間推導(dǎo)出初始種子值,因此每次運行程序時都會獲得不同的種子值。randrangerandom

重要函數(shù)4偽隨機數(shù)>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從給定范圍中選擇一個偽隨機整數(shù)4偽隨機數(shù)>>>fromrandomimport*>>>random()0.7635543105304049>>>random()0.31164370051447243>>>random()0.7039672847873445>>>random()0.5959989547801257用于生成偽隨機浮點值4偽隨機數(shù)假設(shè)選手的發(fā)球回合得分概率是0.70。if<playerwinsserve>:score=score+14偽隨機數(shù)ifrandom()<prob:score=score+1假設(shè)生成一個0~1之間的隨機值。區(qū)間(0,1)的70%正好在0.7的左邊。所以70%的時間隨機數(shù)將小于0.7,而其他30%的次數(shù)將大于等于0.7。一般來說,如果prob表示選手獲勝的概率,則random()<prob就成功地表示了正確的概率。PART5自頂而下的設(shè)計5自頂而下的設(shè)計一種成熟的解決復(fù)雜問題的技術(shù)稱為“自頂向下”。從總問題開始,嘗試用較小的問題來表達解決方案問題變得很小,以至于它們可以輕松得到解決依次使用相同的技術(shù),攻克每個較小的問題把所有的小塊都拼回來,大功告成,得到一個程序PART6頂層設(shè)計6頂層設(shè)計打印介紹獲取輸入:probA,probB,n用probA和probB模擬n局短柄壁球比賽打印playerA和playerB的獲勝報告輸入處理輸出遵循模式:6頂層設(shè)計打印介紹:defmain():printIntro()

6頂層設(shè)計從用戶獲取輸入:probA,probB,n:defmain():printIntro()probA,probB,n=getInputs()6頂層設(shè)計用probA和probB模擬n局短柄壁球比賽:調(diào)用函數(shù)simNGames進行模擬比賽需要模擬的場n模擬使用怎樣的probA和probB的值6頂層設(shè)計用probA和probB模擬n局短柄壁球比賽:defmain():printIntro()probA,probB,n=getInputs()winsA,winsB=simNGames(n,probA,probB)6頂層設(shè)計defmain():printIntro()probA,probB,n=getInputs()winsA,winsB=simNGames(n,probA,probB)printSummary(winsA,winsB)打印playerA和playerB的獲勝報告:PART7關(guān)注點分離7關(guān)注點分離defmain():printIntro()probA,probB,n=getInputs()winsA,winsB=simNGames(n,probA,probB)printSummary(winsA,winsB)7關(guān)注點分離我們已經(jīng)指定了執(zhí)行這些任務(wù)的函數(shù)名稱、參數(shù)和預(yù)期返回值。這些信息稱為函數(shù)的“接口”或“簽名”。唯一關(guān)注的是,如果給出比賽局數(shù)和兩個概率,它必須返回每名選手獲勝的正確局數(shù)。main函數(shù)只關(guān)心每個(子)函數(shù)“做什么”。7關(guān)注點分離圖9.1短柄壁球模擬的一級結(jié)構(gòu)圖7關(guān)注點分離在設(shè)計的每個層次上,接口告訴我們下層的哪些細節(jié)很重要,其他東西都可以暫時忽略確定某些重要特征并忽略其他細節(jié)的一般過程稱為“抽象”可以將自頂向下設(shè)計的整個過程視為發(fā)現(xiàn)有用抽象的系統(tǒng)方法PART8第二層設(shè)計第二課時defprintIntro():print("這個程序模擬了選手A和選手B之間的短柄壘球游戲,每個選手")

print("在發(fā)球階段的得分可能性由一個概率(0和1之間的數(shù)字)來表示,")

print("總是選手A先發(fā)球。")8第二層設(shè)計8第二層設(shè)計defgetInputs():#返回三個參數(shù)probA,probB和na=float(input("A贏得發(fā)球的概率為多少?"))

b=float(input("B贏得發(fā)球的概率是多少?"))

n=int(input("一共模擬多少場比賽?"))

returna,b,n函數(shù)中的變量是該函數(shù)的局部變量。提示輸入獲取三個值,返回給主程序。PART9設(shè)計simNGames9設(shè)計simNGames初始化A和B的勝利場數(shù)為0循環(huán)n次模擬比賽如果A贏A的勝場叫1elseB的勝場加1基本思想是模擬n局比賽,并記錄每名選手的勝利局數(shù)。defsimNGames(n,probA,probB):#模擬n次比賽返回winsA和winsBwinsA=0winsB=0foriinrange(n):9設(shè)計simNGames9設(shè)計simNGames下面模擬一句短柄壘球比賽。更新結(jié)構(gòu)圖以反映這些決定采用一個simOneGame函數(shù)來表示一場比賽以他們的成績?yōu)檩敵?,讓simOneGame返回兩名球員的最終成績9設(shè)計simNGames圖9.2短柄壁球模擬的二級結(jié)構(gòu)圖9設(shè)計simNGamesdefsimNGames(n,probA,probB):winsA=winsB=0foriinrange(n):scoreA,scoreB=simOneGame(probA,probB)ifscoreA>scoreB:winsA=winsA+1else:winsB=winsB+1returnwinsA,winsBPART10第三層設(shè)計10第三層設(shè)計對短柄壁球規(guī)則的邏輯進行編碼:如何記錄誰在發(fā)球呢?我要解決simOneGame問題!需要記錄得分知道是誰在發(fā)球用存儲“A”或“B”的字符串變量10第三層設(shè)計初始化scores為0選手"A"發(fā)球游戲沒結(jié)束時一直循環(huán):模擬任何一個正在發(fā)球的球員的發(fā)球更新游戲狀態(tài)返回scores10第三層設(shè)計defsimOneGame(probA,probB):scoreA=0scoreB=0erving="A"while<condition>:10第三層設(shè)計只要比賽沒結(jié)束,就需要繼續(xù)循環(huán)這個條件到底是什么?將細節(jié)隱藏在另一個函數(shù)gameOver中,如果比賽結(jié)束,則返回True,否則返回False通過查看分數(shù)來判斷游戲是否結(jié)束10第三層設(shè)計圖9.3短柄壁球模擬的第三層結(jié)構(gòu)圖10第三層設(shè)計defsimOneGame(probA,probB):scoreA=0scoreB=0serving="A"whilenotgameOver(scoreA,scoreB):如果A在發(fā)球,那么我們需要使用A的概率,并且根據(jù)發(fā)球的結(jié)果,更新A的分數(shù),或?qū)l(fā)球更改為B。10第三層設(shè)計ifserving=="A":ifrandom()<probA:scoreA=scoreA+1else:serving="B"10第三層設(shè)計ifserving=="A":ifrandom()<probA:scoreA=scoreA+1else:serving="B"else:ifrandom()<probB:scoreB=scoreB+1else:serving="A"10第三層設(shè)計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表示一場壁球游戲的得分#如果游戲結(jié)束,則返回True,否則返回Falsereturna==15orb==1511整理完成fromrandomimportrandomdefmain():printIntro()probA,probB,n=getInputs()winsA,winsB=simNGames(n,probA,probB)printSummary(winsA,winsB)

defprintIntro():

print("這個程序模擬了選手A和選手B之間的短柄壘球游戲,每個選手")

print("在發(fā)球階段的得分可能性由一個概率(0和1之間的數(shù)字)來表示,")

print("總是選手A先發(fā)球。")11整理完成defgetInputs():#返回三個參數(shù)probA,probB和na=float(input("A贏得發(fā)球的概率為多少?"))

b=float(input("B贏得發(fā)球的概率是多少?"))

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表示一場壁球游戲的得分

#如果游戲結(jié)束,則返回True,否則返回Falsereturna==15orb==15

defprintSummary(winsA,winsB):#打印選手的勝利場數(shù)即概率.

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設(shè)計過程總結(jié)12設(shè)計過程總結(jié)自頂向下的設(shè)計實戰(zhàn):從結(jié)構(gòu)圖的最高層開始,一路向下。在每個層次上,我們從總算法開始,然后逐漸將它提煉為精確的代碼。這種方法有時稱為“逐步求精”。將算法表示為一系列較小的問題用較小問題的接口來表示該算法,從而描述算法的細節(jié)為每個小問題開發(fā)一個接口對每個較小的問題重復(fù)此過程PART13自底向上的實現(xiàn)13自底向上的實現(xiàn)當(dāng)我們有一段完整代碼時,即使我們再小心,但當(dāng)我們測試驗證時,還是有時可能會對結(jié)果有些失望。PART14單元測試14單元測試圖9.4短柄壁球模擬的第三層結(jié)構(gòu)圖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)當(dāng)概率相等時,分數(shù)接近。當(dāng)概率相差較大時,比賽就是一邊倒。14單元測試我們可以繼續(xù)這樣的部分實現(xiàn),將組件添加到代碼中,同時測試每個組件。軟件工程師稱這個過程為“單元測試”。獨立測試每個函數(shù)更容易發(fā)現(xiàn)錯誤。當(dāng)你測試整個程序的時候,有可能一切順利。PART15模擬結(jié)果15模擬結(jié)果假設(shè)Denny贏球的概率為55%,比他強一點的選手贏球概率為60%,我們模擬1000次,運行結(jié)果如下:這個程序模擬了選手A和選手B之間的短柄壘球游戲,每個選手在發(fā)球階段的得分可能性由一個概率(0和1之間的數(shù)字)來表示,總是選手A先發(fā)球。A贏得發(fā)球的概率為多少?0.55B贏得發(fā)球的概率是多少?0.6一共模擬多少場比賽?1000

模擬游戲:1000A贏:389(38.9%)B贏:611(61.1%)當(dāng)相差很小時,Denny獲勝的概率大概為三分之一。所以Denny輸?shù)牟辉?。PART16其他設(shè)計技術(shù)16其他設(shè)計技術(shù)自頂向下的設(shè)計是一種非常強大的程序設(shè)計技術(shù),但并不是創(chuàng)建程序的唯一方法。PART17原型與螺旋式開發(fā)17原型與螺旋式開發(fā)另一種設(shè)計方法是從程序或程序組件的簡單版本開始,然后嘗試逐漸添加功能,直到滿足完整的規(guī)格說明。初始的樸素版本稱為“原型”。原型通常會導(dǎo)致一種“螺旋式”開發(fā)過程。設(shè)計、實現(xiàn)并測試一個原型新功能被設(shè)計、實現(xiàn)和測試在開發(fā)過程中,完成許多小循環(huán),原型逐漸擴展為最終的程序17原型與螺旋式開發(fā)例:如何開發(fā)短柄壁球模擬。問題的本質(zhì)在于模擬一個短柄壁球的比賽。我們可能就從simOneGame函數(shù)開始。進一步簡化,的原型可以假設(shè)每名選手有一半對一半的機會贏得每一分,并且只比賽30回合。這需要考慮問題的關(guān)鍵,即處理得分和換發(fā)球。17原型與螺旋式開發(fā)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原型與螺旋式開發(fā)101020...777817原型與螺旋式開發(fā)初始原型。比賽30回合,發(fā)球者總是有50%的獲勝機率。打印出每次發(fā)球后的分數(shù)。添加兩個參數(shù),表示兩名選手的不同概率。比賽直到其中一名選手得到15分。此時,我們有了能工作的一局比賽的模擬。構(gòu)建完整的程序。添加交互式輸入和格式漂亮的結(jié)果報告。擴展進行多局比賽。輸出是每名選手贏得的比賽數(shù)量。階段1階段3階段4階段2階段5PART18設(shè)計的藝術(shù)18設(shè)計的藝術(shù)要注意的是,螺旋式開發(fā)不是自頂向下設(shè)計的替代品。相反,它們是互補的方法。在設(shè)計原型時,你仍然會使用自頂向下的技術(shù)。設(shè)計沒有“唯一正確的方式”。事實上,良好的設(shè)計與科學(xué)一樣是一個創(chuàng)造性的過程。事后可以對設(shè)計細致地分析,但是沒有生成設(shè)計的硬性規(guī)則。課程目標(biāo)小結(jié)

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論