相傳有一個故事,
數學家高斯的小學數學老師出了一道從1+2+3+...+100的習題,
想讓活潑好動的小學生們算一整節課,消耗一下多餘的體力,
結果老師剛說完題目沒過多久,小高斯就算出了答案。
原來,他發現數列兩端可以兩兩配對:1+100,2+99……每一對的和都是101,共有50對,所以總和是5050。讓老師讚嘆不已,也讓老師對這個與眾不同的小高斯刮目相看。
如果 高斯 小時候學過python,會怎麼用python程式來計算 1+2+3+...+100?
先回到故事的起點,小高斯可能會這樣寫:
根據1+2+3+...+100的對稱性,小高斯推導出
def range_sum(start, end):
n = end - start + 1
summation = (start + end) * n // 2
return summation
print( range_sum(start=1, end=100) )
輸出結果
5050
但是小高斯求知若渴,不滿足於此,他想試試看Python可以有多少種不同的實作方式,來算出1+2+3+...+100的和。
根據小高斯學過C/C++的經驗,很快想出python對應的
def range_sum(start, end):
summation = 0
for i in range(start, end+1):
summation += i
return summation
print( range_sum(1, 100) )
輸出結果
5050
然後,思索片刻,小高斯又想到數學老師說,
迭代和遞迴往往彼此擁有等價互通的寫法。又寫出了對應的
def range_sum(start, end):
if start == end:
return start
else:
return range_sum(start, end-1) + end
print( range_sum(1, 100) )
輸出結果
5050
這時候,他又想起電腦老師教過python特有的list comprehension列表生程式,
寫起來乾淨又清爽。
def range_sum(start, end):
numbers = [ i for i in range(start, end+1) ]
return sum( numbers )
print( range_sum(1, 100) )
小高斯發現,其實list comprehension 就已經生成實體的list了,不用額外建立變數,可以直接放在sum裡面做加總計算。
def range_sum(start, end):
return sum( [ i for i in range(start, end+1) ] )
print( range_sum(1, 100) )
輸出結果
5050
小高斯中途休息喝水時,又瞥見桌上的PEP 289的標題就是Generator expressions,還可以使用生成器的方式來動態生成元素,更節省記憶體。
def range_sum(start, end):
return sum( ( i for i in range(start, end+1) ) )
print( range_sum(1, 100) )
輸出結果
5050
小高斯看著輸出畫面,又想到range本身就是一個帶有定義的序列,可以直接放在sum()作加總。
def range_sum(start, end):
return sum( range(start, end+1) )
print( range_sum(1, 100) )
接著,他又想起好像在書上看過,python支持functional programming,函數式計算,一個function的輸出可以傳給另一個function當作輸入。
相當於用add當作運算子,對1,2,3,...,100 做 map reduce,就可以得到1+2+3+...+100。
from functools import reduce
from operator import add
def range_sum(start, end):
return reduce(add, (i for i in range(start, end+1) ) )
print( range_sum(1, 100) )
輸出結果
5050
其中,add也可以不要import,用lambda expression 代替
from functools import reduce
def range_sum(start, end):
return reduce(lambda x,y: x+y, (i for i in range(start, end+1) ) )
print( range_sum(1, 100) )
輸出結果
5050
這時候,小高斯還專注在思考的過程中,
忽然聽見熟悉的下課鐘聲聲響起,噹~噹~噹~噹~噹~噹~噹~噹~
小高斯這才心滿意足地將程式碼存檔,關上電腦,收好課本。
準備到體育館去和同學一起參加下一節的體育課。