Python 標準函式庫中的 math 模組提供大部分科學運算所需之常數與函式, 不過它只支援純量運算, 不支援向量運算, 向量運算須使用第三方套件 Numpy.
本篇測試參考了如下書籍 :
- Python 零基礎入門班 (碁峰 2018, 文淵閣工作室)
- Python 函式庫語法範例字典 (旗標 2019)
- Python 程式設計學習經典 (碁峰 2018)
- The Python 3 Standard Library by Examples (Edison Wesley 2017)
math 模組教學文件參考 :
Python 內建數值處理相關函式參考 :
首先來檢視 random 模組的公開成員, 以下使用一個自訂模組 members, 其 list_members() 函式會列出模組或套件中的公開成員 (即屬性與方法), 參考 :
math 使用前須先用 import 匯入 :
>>> import math
>>> import members
>>> members.list_members(math)
acos <class 'builtin_function_or_method'>
acosh <class 'builtin_function_or_method'>
asin <class 'builtin_function_or_method'>
asinh <class 'builtin_function_or_method'>
atan <class 'builtin_function_or_method'>
atan2 <class 'builtin_function_or_method'>
atanh <class 'builtin_function_or_method'>
ceil <class 'builtin_function_or_method'>
copysign <class 'builtin_function_or_method'>
cos <class 'builtin_function_or_method'>
cosh <class 'builtin_function_or_method'>
degrees <class 'builtin_function_or_method'>
e <class 'float'>
erf <class 'builtin_function_or_method'>
erfc <class 'builtin_function_or_method'>
exp <class 'builtin_function_or_method'>
expm1 <class 'builtin_function_or_method'>
fabs <class 'builtin_function_or_method'>
factorial <class 'builtin_function_or_method'>
floor <class 'builtin_function_or_method'>
fmod <class 'builtin_function_or_method'>
frexp <class 'builtin_function_or_method'>
fsum <class 'builtin_function_or_method'>
gamma <class 'builtin_function_or_method'>
gcd <class 'builtin_function_or_method'>
hypot <class 'builtin_function_or_method'>
inf <class 'float'>
isclose <class 'builtin_function_or_method'>
isfinite <class 'builtin_function_or_method'>
isinf <class 'builtin_function_or_method'>
isnan <class 'builtin_function_or_method'>
ldexp <class 'builtin_function_or_method'>
lgamma <class 'builtin_function_or_method'>
log <class 'builtin_function_or_method'>
log10 <class 'builtin_function_or_method'>
log1p <class 'builtin_function_or_method'>
log2 <class 'builtin_function_or_method'>
modf <class 'builtin_function_or_method'>
nan <class 'float'>
pi <class 'float'>
pow <class 'builtin_function_or_method'>
radians <class 'builtin_function_or_method'>
remainder <class 'builtin_function_or_method'>
sin <class 'builtin_function_or_method'>
sinh <class 'builtin_function_or_method'>
sqrt <class 'builtin_function_or_method'>
tan <class 'builtin_function_or_method'>
tanh <class 'builtin_function_or_method'>
tau <class 'float'>
trunc <class 'builtin_function_or_method'>
可見 math 模組的成員包含了 5 個數學常數與許多數學函數.
1. 常數 :
math 模組內建了五個科學計算中最常用的常數 :
math 模組的常數 | 說明 |
e | 自然指數=2.718281828459045 |
pi | 圓周率=3.141592653589793 |
tau | 圓常數 (圓周與半徑之比, 即 2*pi)=6.283185307179586 |
inf | 無限大=inf (很大的浮點數) |
nan | 非數值=nan (不是數值的一個 float 型態值) |
例如 :
>>> print("math.pi=", math.pi)
math.pi= 3.141592653589793
>>> print("math.e=", math.pi)
math.e= 3.141592653589793
>>> print("math.tau=", math.pi)
math.tau= 3.141592653589793
>>> print("math.nan=", math.nan) # 非數值
math.nan= nan
>>> print("math.inf=", math.inf) # 無窮大
math.inf= inf
>>> math.tau
6.283185307179586
>>> math.pi * 2
6.283185307179586
注意, math.nan 與 math.inf 的資料型態均為 float :
>>> print("type(math.nan)=", type(math.nan))
type(math.nan)= <class 'float'>
>>> print("type(math.inf)=", type(math.inf))
type(math.inf)= <class 'float'>
可以將字串 'nan' 與 'inf' 傳給 float() 函式以產生 nan 與 inf, 例如 :
>>> float('nan')
nan
>>> float('inf')
inf
可以用 math.isnan() 函式來檢驗是否為 nan, 例如 :
>>> math.isnan(math.nan)
True
>>> math.isnan(float('nan'))
True
>>> math.isinf(math.inf)
True
>>> math.isinf(float('inf'))
True
如果要用到負無窮大, 就直接加個負號即可, 即 -math.inf.
2. 函式 :
math 模組提供的函式如下表 :
math 模組的函式 | 說明 |
fabs(x) | 傳回 x 的絕對值 |
fsum(x) | 傳回 x (可迭代物件, 串列或元組, 集合) 的元素總和 |
remainder(x, y) | 傳回 x/y 的餘數=x-n*y, n 為最接近商之整數 (Python 3.7 版新增) |
fmod(x, y) | 傳回 x/y 的模數, 計算整數模式使用 %, 浮點數模數則用 fmod() |
modf(x) | 傳回 x 小數與整數部分組成的 tuple |
sqrt(x) | 傳回 x 的平方根 (x 須為正數) |
pow(x, y) | 傳回 x 的 y 次方 |
floor(x) | 傳回小於或等於 x 的最大整數 (進位函式) |
ceil(x) | 傳回大於或等於 x 的最小整數 (捨位函式) |
trunc(x) | 傳回 x 的整數部分 (無條件捨棄小數) |
gcd(a, b, c, d, ....) | 傳回 a, b, c, d, ... 的最大公因數 |
lcm(a, b, c, d, ....) | 傳回 a, b, c, d, ... 的最小公倍數 (Python 3.9 版新增) |
comb(n, k) | 傳回從 n 個元素中取出 k 個的組合數=n!/(n-k)!, 3.8 版後 |
perm(n, k) | 傳回從 n 個元素中取出 k 個的排列數=n!/(k!(n-k)!), 3.8 版後 |
prod(x) | 傳回 x (串列, 元組, 集合) 所有元素之乘積 (Python 3.8 版新增) |
exp(x) | 傳回 x 的自然指數 |
expm1(x) | 傳回 x 的自然指數減 1 (Python 3.2 新增) |
log(x) | 傳回 x 的自然對數 (以 e 為底) |
log2(x) | 傳回 x 的以 2 為底的對數 (Python 3.3 新增) |
log10(x) | 傳回 x 的自然對數 (以 10 為底) |
log1p(x) | 傳回 x + 1 的自然對數 (以 e 為底) |
factorial(x) | 傳回 x 的階乘 x! |
sin(x) | 傳回 x 的正弦值 |
cos(x) | 傳回 x 的餘弦值 |
tan(x) | 傳回 x 的正切值 |
asin(x) | 傳回 x 的反正弦值 |
acos(x) | 傳回 x 的反餘弦值 |
atan(x) | 傳回 x 的反正切值 |
atan2(y,x) | 傳回 y/x 的反正切值 |
radians(x) | 傳回角度 x 之弧度 (角度轉弧度) |
degrees(x) | 傳回弧度 x 之角度 (弧度轉角度) |
sinh(x) | 傳回 x 的雙曲正弦值 |
cosh(x) | 傳回 x 的雙曲餘弦值 |
tanh(x) | 傳回 x 的雙曲正切值 |
isinf(x) | 判斷 x 是否為 inf (傳回 True/False) |
isnan(x) | 判斷 x 是否為 NaN (傳回 True/False) |
fabs() 會傳回絕對值 (正數), 例如 :
>>> math.fabs(-1.234) # 絕對值
1.234
內建函式 sum() 可以傳入數列 (多參數), 串列, 或元組, 但 fsum() 不能傳入數列, 因為它只能傳入一個可迭代的容器型態參數, 例如串列, 元組, 或集合等, fsum() 會傳回可迭代物件所有元素之和, 例如 :
>>> math.fsum([1, 2, 3]) # 計算串列元素和
6.0
>>> math.fsum((1, 2, 3)) # 計算元組元素和
6.0
>>> math.fsum({1, 2, 3}) # 計算集合元素和
6.0
remainder(x, y) 函式顧名思義是傳回 x/y 之餘數, 但其計算方式為 x-n*y, 其中 n 是最接近 x/y 商之整數, 例如 :
>>> math.remainder(13, 3) # 13/3 餘數是 1=13-4*3
1.0
>>> math.remainder(23.5, 5) # 傳回 -1,5=23.5-5*5
-1.5
此處餘數並非 0, 因 23.5/5 商為 4.7, 最接近之整數為 5, 故傳回 23.5-5*5=-1.5.
fmod(x, y) 會傳回 x/y 之模數, 計算整數模數會用 % 運算子; 計算浮點數模數則用 fmod() :
>>> 23 % 5
3
>>> math.fmod(23.5, 5)
3.5
>>> math.fmod(5, -2)
1.0
>>> 5 % -2
-1
modf(x) 則會把浮點數的小數與整數部分拆開, 組成 (小數, 整數) 之元組傳回 (帶符號) :
>>> math.modf(3.14159)
(0.14158999999999988, 3.0)
>>> math.modf(-3.14159)
(-0.14158999999999988, -3.0)
>>> math.modf(-3.14159e2)
(-0.15899999999999181, -314.0)
開平方函式 sqrt() 與次方函式 pow() 都屬於冪函數, sqrt(x) 其實等於 pow(x, 0.5) :
>>> math.sqrt(2) # 開平方
1.4142135623730951
>>> math.pow(2, 4) # 2 的 4 次方
16.0
>>> math.pow(2, 0.5) # 開平方就是 0.5 次方
1.4142135623730951
>>> math.pow(8, 1/3) # 開立方就是 1/3 次方
2.0
floor(x), ceil(x), 與 trunc(x) 是近似函式 (math 模組沒有四捨五入或五捨六入函式), 它們會傳回浮點數的近似值, floor(x) 傳回 x 的地板整數; ceil(x) 傳回 x 的天花板整數; 而 trunc() 則是將小數部分完全捨去只傳回整數部分, 例如 :
>>> math.floor(3.14) # 小於或等於 3.14 的最大整數=3
3
>>> math.floor(-3.14) # 小於或等於 -3.14 的最大整數=-4
-4
>>> math.ceil(3.14) # 大於或等於 3.14 的最小整數=3
4
>>> math.ceil(-3.14) # 大於或等於 -3.14 的最小整數=-3
-3
>>> math.trunc(3.14) # 捨去小數部分
3
>>> math.trunc(-3.14) # 捨去小數部分
-3
gcd() 會傳回傳入參數數列 (正整數) 的最大公因數, 而 lcm() 則會傳回其最小公倍數 (Python 3.9 新增功能) :
>>> math.gcd(6, 21) # 最大公因數
3
>>> math.lcm(12, 8, 3, 4) # 最小公倍數
24
perm(n, k) 是從 n 個元素中取出 k 個不重複的排列方式, 等於 n!/(n-k)!, 此函式須在 Python 3.8 以上版本才有支援, 例如 :
>>> math.perm(6, 2)
30
>>> math.factorial(6)/(math.factorial(6-2))
30.0
exp(x) 會傳回 x 的自然指數值; log(x) 則會傳回 x 以 e 為底的自然對數值, 兩者互為反函數 :
>>> math.exp(1) # 自然指數
2.718281828459045
>>> math.log(1) # 自然對數
0.0
>>> math.log(math.e) # ln(e)=1
1.0
在 Python 3.2 版新增了 expm1(x) 函式, 其值為 exp(x)-1, 對於曉得浮點數 x 而言, exp(x)-1 可能會有誤差, expm1(x) 則能保持同樣運算的浮點數精度, 例如 :
>>> math.exp(1e-5)-1
1.0000050000069649e-05
>>> math.expm1(1e-5)
1.0000050000166667e-05
當 x 很小時, 用 exp(x)-1 來運算的話, 小數部分精確度會不足, 應改用 expm1().
任何基底的 1 的對數結果都是 0, 當 0 < x < 1 時對數都是負值, 越接近 0 越負, 0 的對數是負無限大, 故為了讓很小的數取對數仍是正值, 會將其加 1 後再取對數, 即 log1p() 之用途, 例如 :
>>> math.log(1e-5)
-11.512925464970229
>>> math.log(1e-10)
-23.025850929940457
>>> math.log(1e-100)
-230.25850929940458
>>> math.log1p(1e-5)
9.99995000033333e-06
>>> math.log1p(1e-10)
9.999999999500001e-11
>>> math.log1p(1e-100)
1e-100
可見當 x 越小時, log1p() 的值越接近 x. Python 3.3 版新增了以 2 為底的 log2(x) :
>>> math.log2(2)
1.0
>>> math.log2(4)
2.0
>>> math.log2(64)
6.0
常用對數則是以 10 為底, 例如 :
>>> math.log10(10) # 常用對數
1.0
>>> math.log10(100) # 常用對數
2.0
factorial(x) 會傳回 x 階乘 :
>>> math.factorial(3) # 3!=3*2*1=6
6
sin(x), cos(x), tan(x) 為三角函數, 其中 tan(x)=sin(x)/cos(x), 數學上的另外三個三角函數 csc(), sec(), 與 cot(x) 分別為其倒數, 故 math 並未提供. 注意, 傳入參數均為弧度, 角度須先用 radians() 轉成弧度, 例如 :
>>> math.radians(30) # 30 度=math.pi/6
0.5235987755982988
>>> math.radians(45) # 45 度=math.pi/4
0.7853981633974483
>>> math.radians(60) # 60 度=math.pi/3
1.0471975511965976
>>> math.radians(90) # 90 度=math.pi/2
1.5707963267948966
>>> math.radians(180) # 180 度=math.pi
3.141592653589793
>>> math.degrees(math.pi/6) # math.pi/6=30 度
29.999999999999996
>>> math.degrees(math.pi/4) # math.pi/4=45 度
45.0
>>> math.degrees(math.pi/3) # math.pi/3=60 度
59.99999999999999
>>> math.degrees(math.pi/2) # math.pi/2=90 度
90.0
>>> math.degrees(math.pi) # 180 度=math.pi/2
180.0
>>> math.sin(math.radians(30)) # sin(30)=0.5
0.49999999999999994
>>> math.sin(math.radians(45)) # sin(45)=math.sqrt(2)/2
0.7071067811865476
>>> math.sqrt(2)/2
0.7071067811865476
>>> math.sin(math.radians(60)) # sin(60)=math.sqrt(3)/2
0.8660254037844386
>>> math.sqrt(3)/2
0.8660254037844386
>>> math.sin(math.radians(90)) # sin(90)=1
1.0
>>> math.cos(math.radians(30)) # cos(30)=math.sqrt(3)/2
0.8660254037844387
>>> math.cos(math.radians(45)) # cos(45)=math.sqrt(2)/2
0.7071067811865476
>>> math.cos(math.radians(60)) # cos(30)=0.5
0.5000000000000001
>>> math.cos(math.radians(90)) # cos(90)=0
6.123233995736766e-17
可見 cos(90) 趨近於 0, 使得 tan(90) 趨近於無限大, 例如 :
>>> math.tan(math.radians(30))
0.5773502691896257
>>> math.sin(math.radians(30))/math.cos(math.radians(30))
0.5773502691896256
>>> math.tan(math.radians(45))
0.9999999999999999
>>> math.sin(math.radians(45))/math.cos(math.radians(45))
1.0
>>> math.tan(math.radians(60))
1.7320508075688767
>>> math.sin(math.radians(60))/math.cos(math.radians(60))
1.7320508075688767
>>> math.tan(math.radians(90))
1.633123935319537e+16
>>> math.sin(math.radians(90))/math.cos(math.radians(90))
1.633123935319537e+16
asin(x), acos(x), 與 atan(x) 分別為 sin(x), cos(x), 與 tan(x) 的反函數, 其傳回值同樣是弧度, 須利用 degrees() 轉成角度, 例如 :
>>> math.asin(0.5)
0.5235987755982989 # 這是弧度
>>> math.degrees(math.asin(0.5))
30.000000000000004
>>> math.degrees(math.asin(0.7071))
44.99945053347443
>>> math.degrees(math.asin(0.866))
59.997089068811974
>>> math.degrees(math.asin(1))
90.0
>>> math.degrees(math.acos(0.866))
30.002910931188026
>>> math.degrees(math.acos(0.7071))
45.00054946652557
>>> math.degrees(math.acos(0.5))
60.00000000000001
>>> math.degrees(math.acos(0))
90.0
>>> math.degrees(math.atan(0.5/0.866))
30.000727780827372
>>> math.degrees(math.atan(0.701/0.701))
45.0
>>> math.degrees(math.atan(0.866/0.5))
59.999272219172624
>>> math.degrees(math.atan(math.inf)) # 1/0 為無限大
90.0
>>> math.degrees(math.atan2(0.5, 0.866)) # 第一參數 sin 值, 第二參數 cos 值
30.000727780827372
>>> math.degrees(math.atan2(0.701, 0.701))
45.0
>>> math.degrees(math.atan2(0.866, 0.5))
59.999272219172624
>>> math.degrees(math.atan2(1, 0))
90.0
math 模組提供的雙曲函式有三個 : sinh(x), cosh(h), 與 tanh(x), 與三角函數類似, 其餘的三個雙曲函數 csch, cosh, 以及 coth 分別是其倒數, 即 csch=1/sinh, sech=cosh, coth=1/tanh. 例如 :
>>> math.sinh(0)
0.0
>>> math.sinh(1)
1.1752011936438014
>>> math.sinh(-1)
-1.1752011936438014
>>> math.cosh(0)
1.0
>>> math.cosh(1)
1.5430806348152437
>>> math.cosh(-1)
1.5430806348152437
沒有留言:
張貼留言