正如我們前幾節(jié)課中所學(xué)到的,在Python 程序中,如果把一個循環(huán)放在另一個循環(huán)體內(nèi),那么就可以形成循環(huán)嵌套。循環(huán)嵌套既可以是 for 循環(huán)嵌套 while 循環(huán),也可以是 while 循環(huán)嵌套 for 循環(huán),即各種類型的循環(huán)都可以作為外層循環(huán),各種類型的循環(huán)也都可以作為內(nèi)層循環(huán)。
當(dāng)程序遇到循環(huán)嵌套時,如果外層循環(huán)的循環(huán)條件允許,則開始執(zhí)行外層循環(huán)的循環(huán)體,而內(nèi)層循環(huán)將被外層循環(huán)的循環(huán)體來執(zhí)行(只是內(nèi)層循環(huán)需要反復(fù)執(zhí)行自己的循環(huán)體而己)。只有當(dāng)內(nèi)層循環(huán)執(zhí)行結(jié)束且外層循環(huán)的循環(huán)體也執(zhí)行結(jié)束時,才會通過判斷外層循環(huán)的循環(huán)條件,決定是否再次開始執(zhí)行外層循環(huán)的循環(huán)體。
根據(jù)上面分析,假設(shè)外層循環(huán)的循環(huán)次數(shù)為 n 次,內(nèi)層循環(huán)的循環(huán)次數(shù)為 m 次,那么內(nèi)層循環(huán)的循環(huán)體實際上需要執(zhí)行n × m次。循環(huán)嵌套的執(zhí)行流程圖如圖 1 所示:
圖 1 循環(huán)嵌套的執(zhí)行流程圖
從圖 1 來看,循環(huán)嵌套就是把內(nèi)層循環(huán)當(dāng)成外層循環(huán)的循環(huán)休。只有內(nèi)層循環(huán)的循環(huán)條件為假時,才會完全跳出內(nèi)層循環(huán),才可以結(jié)束外層循環(huán)的當(dāng)次循環(huán),開始下一次循環(huán)。
學(xué)完前面的幾個章節(jié)后,我覺得有必要在這里帶大家做一些練習(xí)來鞏固之前所學(xué)的知識,雖然迄今為止我們學(xué)習(xí)的內(nèi)容只是Python的冰山一角,但是這些內(nèi)容已經(jīng)足夠我們來構(gòu)建程序中的邏輯。對于編程語言的初學(xué)者來說,在學(xué)習(xí)了Python的核心語言元素(變量、類型、運(yùn)算符、表達(dá)式、分支結(jié)構(gòu)、循環(huán)結(jié)構(gòu)等)之后,必須做的一件事情就是嘗試用所學(xué)知識去解決現(xiàn)實中的問題,換句話說就是鍛煉自己把用人類自然語言描述的算法(解決問題的方法和步驟)翻譯成Python代碼的能力,而這件事情必須通過大量的練習(xí)才能達(dá)成。
一個復(fù)雜的現(xiàn)實問題,實際上就是拆解成若干個邏輯構(gòu)造,利用判斷和循環(huán),化繁為簡!
這節(jié)課我們集中復(fù)習(xí)一下if,while,for等幾個主要邏輯構(gòu)造方法的應(yīng)用與實戰(zhàn)。
我們在本章為大家整理了一些經(jīng)典的案例和習(xí)題,希望通過這些例子,一方面幫助大家鞏固之前所學(xué)的Python知識,另一方面幫助大家了解如何建立程序中的邏輯以及如何運(yùn)用一些簡單的算法解決現(xiàn)實中的問題。
實例1:尋找水仙花數(shù)
說明:水仙花數(shù)也被稱為超完全數(shù)字不變數(shù)、自戀數(shù)、自冪數(shù)、阿姆斯特朗數(shù),它是一個3位數(shù),該數(shù)字每個位上數(shù)字的立方之和正好等于它本身,例如:1^3 + 5^3+ 3^3=153。
for num in range(100, 1000):
low = num % 10
mid = num // 10 % 10
high = num // 100
if num == low ** 3 + mid ** 3 + high ** 3:
print(num)
在上面的代碼中,我們通過整除和求模運(yùn)算分別找出了一個三位數(shù)的個位、十位和百位,這種小技巧在實際開發(fā)中還是常用的。
實例2:百錢百雞問題(窮舉法)
> **說明**:百錢百雞是我國古代數(shù)學(xué)家[張丘建](https://baike.baidu.com/item/%E5%BC%A0%E4%B8%98%E5%BB%BA/10246238)在《算經(jīng)》一書中提出的數(shù)學(xué)問題:雞翁一值錢五,雞母一值錢三,雞雛三值錢一。百錢買百雞,問雞翁、雞母、雞雛各幾何?翻譯成現(xiàn)代文是:公雞5元一只,母雞3元一只,小雞1元三只,用100塊錢買一百只雞,問公雞、母雞、小雞各有多少只?
for x in range(0, 20):
for y in range(0, 33):
z = 100 – x – y
if 5 * x + 3 * y + z / 3 == 100:
print(‘公雞: %d只, 母雞: %d只, 小雞: %d只’ % (x, y, z))
上面使用的方法叫做窮舉法,也稱為暴力搜索法,這種方法通過一項一項的列舉備選解決方案中所有可能的候選項并檢查每個候選項是否符合問題的描述,最終得到問題的解。這種方法看起來比較笨拙,但對于運(yùn)算能力非常強(qiáng)大的計算機(jī)來說,通常都是一個可行的甚至是不錯的選擇,而且問題的解如果存在,這種方法一定能夠找到它。大家可以想一下“雞兔同籠”問題,是不是很有啟發(fā)!
實例3:CRAPS賭博游戲
說明:CRAPS又稱花旗骰,是美國拉斯維加斯非常受歡迎的一種的桌上賭博游戲。該游戲使用兩粒骰子,玩家通過搖兩粒骰子獲得點數(shù)進(jìn)行游戲。簡單的規(guī)則是:玩家第一次搖骰子如果搖出了7點或11點,玩家勝;玩家第一次如果搖出2點、3點或12點,莊家勝;其他點數(shù)玩家繼續(xù)搖骰子,如果玩家搖出了7點,莊家勝;如果玩家搖出了第一次搖的點數(shù),玩家勝;其他點數(shù),玩家繼續(xù)要骰子,直到分出勝負(fù)。
from random import randint
money = 1000
while money > 0:
print(‘你的總資產(chǎn)為:’, money)
needs_go_on = False
while True:
debt = int(input(‘請下注: ‘))
if 0 < debt <= money:
break
first = randint(1, 6) + randint(1, 6)
print(‘玩家搖出了%d點’ % first)
if first == 7 or first == 11:
print(‘玩家勝!’)
money += debt
elif first == 2 or first == 3 or first == 12:
print(‘莊家勝!’)
money -= debt
else:
needs_go_on = True
while needs_go_on:
needs_go_on = False
current = randint(1, 6) + randint(1, 6)
print(‘玩家搖出了%d點’ % current)
if current == 7:
print(‘莊家勝’)
money -= debt
elif current == first:
print(‘玩家勝’)
money += debt
else:
needs_go_on = True
print(‘你破產(chǎn)了, 游戲結(jié)束!’)
實例4:生成**斐波那契數(shù)列**的前20個數(shù)
說明:斐波那契數(shù)列(Fibonacci sequence),又稱黃金分割數(shù)列,是意大利數(shù)學(xué)家萊昂納多·斐波那契(Leonardoda Fibonacci)在《計算之書》中提出一個在理想假設(shè)條件下兔子成長率的問題而引入的數(shù)列,所以這個數(shù)列也被戲稱為兔子數(shù)列。斐波那契數(shù)列的特點是數(shù)列的前兩個數(shù)都是1,從第三個數(shù)開始,每個數(shù)都是它前面兩個數(shù)的和,形如:1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, …。斐波那契數(shù)列在現(xiàn)代物理、準(zhǔn)晶體結(jié)構(gòu)、化學(xué)等領(lǐng)域都有直接的應(yīng)用。
a = 0
b = 1
for _ in range(20):
a, b = b, a + b
print(a, end=’ ‘)
實例5:找出10000以內(nèi)的“完全數(shù)”。
說明:完全數(shù)又稱為完美數(shù)或完備數(shù),它的所有的真因子(即除了自身以外的因子)的和(即因子函數(shù))恰好等于它本身。例如:6(6=1+2+3)和28(28=1+2+4+7+14)就是完美數(shù)。完美數(shù)有很多神奇的特性,有興趣的可以自行了解。
import math
for num in range(1, 10000):
result = 0
for factor in range(1, int(math.sqrt(num)) + 1):
if num % factor == 0:
result += factor
if factor > 1 and num // factor != factor:
result += num // factor
if result == num:
print(num)