in python_数学 in python
數(shù)學(xué)算法
本節(jié)內(nèi)容將介紹數(shù)學(xué)算法。主要包含數(shù)學(xué)上幾個基本問題,算術(shù)分析方法,斐波那契數(shù)列問題,篩選算法,以及最大公約數(shù)問題。
知識點(diǎn)數(shù)學(xué)幾個基本問題
算術(shù)分析方法
斐波那契數(shù)列問題
篩選算法
最大公約數(shù)問題
數(shù)學(xué)上幾個基本問題
在編程界,有這么幾個經(jīng)典的數(shù)學(xué)問題,這里給大家簡單介紹下。
3 n+1 問題
對于任意大于 1 的自然數(shù) n,若該數(shù)為偶數(shù)則將其變?yōu)樵瓉淼囊话?#xff0c;若為奇數(shù)則將其變?yōu)? n+1。反復(fù)進(jìn)行上述過程,直到結(jié)果為 1 時停止。這就是著名的“3 n+1”問題。要求輸入 n,輸出按“3 n+1”規(guī)則變換到 1 所需要的數(shù)字變換次數(shù)。(n<=10^9)
題目描述:
3 n+1 問題是一個簡單有趣而又沒有解決的數(shù)學(xué)問題。這個問題是由 L. Collatz 在 1937 年提出的。克拉茲問題(Collatz problem)也被叫做 hailstone 問題、3n+1 問題、Hasse 算法問題、Kakutani 算法問題、Thwaites 猜想或者 Ulam 問題。克拉茲問題的特殊之處在于:盡管很容易將這個問題講清楚,但直到今天仍不能保證這個問題的算法對所有可能的輸入都有效——即至今沒有人證明對所有的正整數(shù)該過程都終止。
問題如下:輸入一個正整數(shù) n;
如果 n=1 則結(jié)束;
如果 n 是奇數(shù),則 n 變?yōu)?3 n+1,否則 n 變?yōu)?n/2;
轉(zhuǎn)入第 2 步。
例子:
input:7
output:[7,22,11,34,17,52,26,13,40,20,10,5,16,8,4,2,1] 16
參考代碼如下:
def function(num):
mylist=[num]
while num!=1:
if num%2==1: #如果為奇數(shù)
num=3*num+1
mylist.append(num)
else: #為偶數(shù)
num=num//2
mylist.append(num)
return mylist,len(mylist)-1
print(function(43))
尋找最值問題
在諸多數(shù)學(xué)問題,最值問題一直是爭論的主題。在求最值的探索的過程,如何更快更好地得到最值,一代又一代理論科學(xué)家做出很大的貢獻(xiàn),逐漸衍化出來很多排序算法。關(guān)于排序算法的知識點(diǎn),我們將在接下來的章節(jié)里介紹,這里將只對最大值,最小值進(jìn)行簡單討論。
最大值求解
給定一個列表 [2, 4, 9, 7, 19, 94, 5],請編寫 find_max 函數(shù),該函數(shù)返回列表的最大值。
這個函數(shù)很容易,相信大家一定能夠自行編寫出來。
參考代碼如下:
def find_max(nums):
max = nums[0]
for x in nums:
if x > max:
max = x
print(max)
?
def main():
find_max([2, 4, 9, 7, 19, 94, 5])
?
if __name__ == '__main__':
main()
最小值求解
定一個列表 [2, 4, 9, 7, 19, 94, 5],請編寫 find_min 函數(shù),該函數(shù)返回列表的最小值。
這個函數(shù)也很容易,相信大家一定能夠自行編寫出來。
參考代碼如下:
def find_min(nums):
min=nums[0]
for x in nums:
if x
min=x
pritn(min)
?
def main():
find_max([2, 4, 9, 7, 19, 94, 5])
?
if __name__ == '__main__':
main()
最大公約數(shù)/最小公倍數(shù)
在介紹最大公約數(shù)和最小公倍數(shù)之前,我們先來介紹下歐幾里得算法
歐幾里得算法
歐幾里得算法又稱輾轉(zhuǎn)相除法,用來求兩個正整數(shù)的最大公約數(shù)。以 1997 和 615 為例,用歐幾里得算法求解如下:
1997=615*3+152
615=152*4+7
152=7*21+5
7=5*1+2
5=2*2+1
2=1*2+0
當(dāng)被加的數(shù)為 0 時,可以得出,1997 和 615 的最大公約數(shù)為 1。
以上做法的依據(jù)是以下定理:
兩個整數(shù)的最大公約數(shù)等于其中較小的那個數(shù)和兩數(shù)相除余數(shù)的最大公約數(shù)。
用數(shù)學(xué)表示為:gcd(a,b)=gcd(b,amodb)
并可以證明歐幾里得算法一定能在有限步內(nèi)結(jié)束。
利用圖形可以更直觀地理解歐幾里得算法
程序設(shè)計:
算法思想:a,b 始終扮演被除數(shù)和除數(shù)的角色。
最大公約數(shù)(greatest common divisor)縮寫為 gcd
參考代碼如下:
def gcd(a,b):
while b:
r=a%b
a=b #經(jīng)過一次求余數(shù),進(jìn)入第二輪相除,即b的值扮演了被除數(shù)的角色
b=r #r的值扮演了余數(shù)的角色
return a #這里return a的原因是,b作為在最后一輪的除數(shù)已經(jīng)幅值給了a
而對于最小公倍數(shù)則有以下思路求解:
a,b 兩個數(shù)的最小公倍數(shù)乘以他們的最大公約數(shù)約等于 a 和 b 本身的乘積
即LCM(a,b)GCD(a,b)=ab
所以最小公倍數(shù)的求解代碼如下:
def lcm(a,b):
return a*b//gcd(a,b)
請大家編程,構(gòu)造一個 three_gcd 和 three_lcm 函數(shù),該函數(shù)完成三個數(shù)的最大公因數(shù)和最小公倍數(shù)的求解
例子:
input:2,7,6
output: gcd :1 lcm: 84
思路:
計算三個數(shù)的最大公約數(shù)時,利用之前寫好的計算 2 個數(shù)的最大公約數(shù)的方法,先算出 a,b 的公約數(shù),再用 a,b 的公約數(shù)與 c 再代入方法,此時返回的值就是三個數(shù)的最大公約數(shù)了。對于三個數(shù)的最小公倍數(shù),繼續(xù)嵌套,先求出兩個數(shù)的,再求與第三個數(shù)的最小公倍數(shù)。
參考代碼如下:
def gcd(a,b):
while b:
r=a%b
a=b #經(jīng)過一次求余數(shù),進(jìn)入第二輪相除,即b的值扮演了被除數(shù)的角色
b=r #r的值扮演了余數(shù)的角色
return a #這里return a的原因是,b作為在最后一輪的除數(shù)已經(jīng)幅值給了a
def lcm(a,b):
return a*b//gcd(a,b)
def three_gcd(a,b,c):
return gcd(gcd(a,b),c)
def three_lcm(a,b,c):
return lcm(a,b)*c//gcd(gcd(a,b),c)
def main():
a=2
b=7
c=6
print("a:",a)
print("b:",b)
print("c:",c)
print("gcd(",a,",",b,",",c,"):",three_gcd(a,b,c))
print("lcm(",a,",",b,",",c,"):",three_lcm(a,b,c))
if __name__=='__main__':
main()
算術(shù)分析方法
在數(shù)學(xué)問題中,有很多算術(shù)分析方法。包括二分法,牛頓遞歸等等。我們將在接下來的章節(jié)里,逐一介紹這兩種種方法。
二分法
二分法:對于區(qū)間[a,b]上連續(xù)不斷且 f(a)·f(b)<0 的函數(shù) y=f(x),通過不斷地把函數(shù) f(x)的零點(diǎn)所在的區(qū)間一分為二,使區(qū)間的兩個端點(diǎn)逐步逼近零點(diǎn),進(jìn)而得到零點(diǎn)近似值的方法叫二分法。
注:定義來自百度百科。
給定精確度 flex,用二分法求函數(shù) f(x) 零點(diǎn)近似值的步驟如下:確定區(qū)間 [a,b],驗證 f(a)*f(b)<0,給定精確度 flex
求區(qū)間 (a,b) 的中點(diǎn) c
計算 f(c):如果 f(c)=0,則 c 就是函數(shù)的零點(diǎn)
如果 f(a)*f(c)<0,則令 b=c
如果 f(c)*f(b)<0, 則令 a=c
判斷是否達(dá)到精確度 flex,即若 |a-b|< flex,則得到零點(diǎn)近似值 a(或 b),否則重復(fù) 2-3 步驟
例子:請在[1,1000]區(qū)間內(nèi),找到 x^3-2*x-5 的零點(diǎn)
import math
def bisection(function, a, b): #指定函數(shù)function,指定區(qū)間[a,b]
start = a
end = b
if function(a) == 0: #a即為零點(diǎn)
return a
elif function(b) == 0: #b即為零點(diǎn)
return b
elif function(a) * function(b) > 0: #二分法無法在該區(qū)間找到零點(diǎn)
print("couldn't find root in [a,b]")
return
else: #f(a)*f(b)<0 的情況
mid = (start + end) / 2
while abs(start - mid) > 10**-7: # 精確度設(shè)置為10**-7
if function(mid) == 0:
return mid
elif function(mid) * function(start) < 0:
end = mid
else:
start = mid
mid = (start + end) / 2
return mid
?
def f(x):
return math.pow(x, 3) - 2*x - 5
if __name__ == "__main__":
print(bisection(f, 1, 1000))
牛頓法
在數(shù)值分析里面, 牛頓法(亦稱牛頓拉弗森法)是一種方法,用于查找更好的根(或零點(diǎn))的例子尋根算法。牛頓法也被用于求函數(shù)的最值。由于函數(shù)取最值的點(diǎn)處的導(dǎo)數(shù)值為零,故可用牛頓法求導(dǎo)函數(shù)的零點(diǎn),其迭代式為
關(guān)于牛頓法和擬牛頓法的區(qū)別,請參考牛頓法和擬牛頓法這篇回答
例子:請用牛頓法,求函數(shù) x*3-2x-5 在 3 附近的零點(diǎn)
參考代碼如下:
def newton(function,function1,start):
#function 是 f(x) function1 是 f(x)的導(dǎo)函數(shù),即f'(x)
x_n=start
while True:
x_n1=x_n-function(x_n)/function1(x_n) #遞歸式
if abs(x_n-x_n1) < 10**-5:
return x_n1
x_n=x_n1
def f(x):
return (x**3)-2*x-5
def f1(x):
return 3*(x**2)-2
if __name__=="__main__":
print(newton(f,f1,3))
問題升級:如果題目不提供導(dǎo)函數(shù),只提供本函數(shù)表達(dá)式,但是提供一個合理區(qū)間,如何求解該區(qū)間內(nèi)的零點(diǎn)?
還是采用牛頓法的思路,導(dǎo)函數(shù)可以采用斜率不斷遞歸的方式。
參考代碼如下:
def intersection(function,start1,start2):
#function 是 f(x),start1,start2 是區(qū)間端點(diǎn)
x_n=start1
x_n1=start2
while True:
x_n2=x_n1-(function(x_n1)/((function(x_n1)-function(x_n))/(x_n1-x_n))) # 遞歸式
if abs(x_n2-x_n1) < 10**-5:
return x_n2
x_n=x_n1
x_n1=x_n2
def f(x):
return (x**3)-2*x-5
if __name__=="__main__":
print(intersection(f,3,3.5))
斐波那契數(shù)列問題
斐波那契數(shù)列(Fibonacci sequence),又稱黃金分割數(shù)列、因數(shù)學(xué)家列昂納多·斐波那契(Leonardoda Fibonacci)以兔子繁殖為例子而引入,故又稱為“兔子數(shù)列”,指的是這樣一個數(shù)列:1、1、2、3、5、8、13、21、34...
在數(shù)學(xué)上,費(fèi)波那契數(shù)列是以遞歸的方法來定義的:F(0) = 0
F(1) = 1
F(n) = F(n - 1) + F(n - 2) (n >= 2)
注:定義來自百度百科。
從數(shù)列上看,我們能看到這是一個典型的遞歸函數(shù),python 遞歸方法實現(xiàn)。
我們在這里將介紹斐波那契數(shù)列的 3 種用 python 方法實現(xiàn)。使用 python 遞歸方法實現(xiàn)斐波那契數(shù)列
思路:f(n)=f(n-1)+f(n),我們直接使用 python 遞歸方法實現(xiàn)斐波那契數(shù)列
參考代碼如下:
def fibo(num):
if num==1:
return 1
elif num==2:
return 1
elif num>2:
return fibo(num-1)+fibo(num-2)
else:
print("False")
代碼分析:遞歸函數(shù)特點(diǎn),在函數(shù)內(nèi)部調(diào)用自身本身;所以函數(shù)必須要求調(diào)用有底線,不能無窮向下調(diào)用,斐波那契數(shù)列的底線在 n=1 與 n=2
2. 使用 python 獨(dú)特的列表實現(xiàn)斐波那契數(shù)列
很多遞歸函數(shù)對于 python 來說非常簡單,因為 python 有個獨(dú)特的數(shù)據(jù)類型 list 列表,list 是動態(tài)的我們可以在尾部追加數(shù)據(jù),這樣一來斐波那契數(shù)列就是簡單的加法游戲了。
參考代碼如下
def fibo(num):
if num==1:
return [1]
elif num==2:
return [1,1]
l=[1,1]
for i in range(2,num):
l.append(l[-2]+l[-1]) #將列表最后兩項的值求和,將值添加到列表最后
return l
?
print(fibo(10))
3. 使用 while 循環(huán)實現(xiàn)
def fibo(num):
a=1
b=1
i=0
l=[]
while i < num:
l.append(a)
a,b=a+b,a
i=i+1
return l
print(fibo(10))
關(guān)于斐波那契數(shù)列用矩陣分解的思路,這里就不詳述了,如果大家對矩陣分解的思路感興趣,請自行探索。
總結(jié)
以上是生活随笔為你收集整理的in python_数学 in python的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: richtextbox自动滚动到最下面_
- 下一篇: python类型提示包 检查静态类型_P