前言:
最近在複習我的 Python 語言,有個小小的發現,所以記錄一下到我的部落格裡面,
大家都知道, Python 假如要使用數學的三角函數,需要 import math 數學函數模組進來。這裡來個簡單的數學小挑戰,假如不用數學模組,也不准用級數展開,可以不可以直接算出數學上的 Sin(x), Cos(x) 函數呢 ?
複數:
Python 是很特殊的語言,它居然直接支援複數的算術運算耶,而且還是系統內建的。這樣可好玩了,基本數學的三角函數不是內建的,然後複數運算居然是內建的。然且讓人驚異的是,系統對複數的數學運算支援得非常完整,連複數的n次方運算 (x^n) 都完全的支援。
這下可好了,這樣不是直接用尤拉公式直接可以算出 sin(x), cos(x) 了呀,何須import math 數學函數模組了咩!(來玩一下好玩的數學吧)
尤拉公式 (Euler's Formula):
物理系學生絕對不陌生的,大名鼎鼎,於1748年所發表的尤拉公式
這個公式是說,一個自然對數底e (=2.718281828...) 的純虛數 ix 次方,最後會變成跟三角函數有關,等於 cos(x) 加上虛數的 sin(x)。
真得是很神奇的公式餒,看似無關的指數,透過這個公式,居然會跟三角函數關聯在一起。
尤拉公式在數學、物理和工程領域應用廣泛。物理學家理察·費曼將尤拉公式稱為:「我們的珍寶」和「數學中最非凡的公式」。舉例來說,我們會利用複數來求解微分方程,或偏微分方程式。我們會利用尤拉公式中的 sin(x), cos(x) 恰為弦波的特性,利用複數平面把弦波變成 e(ix) 的自然對數的指數,這樣微分方程就很容易跟符號上可以很精簡漂亮地被求解出來囉。
所以導致電學上常見的,交流下的歐姆定律,其電抗是個複數,其實跟這個公式有關。
電磁波裡有名的 Smith Chart,傳輸線理論裡面無處不見的阻抗,阻抗匹配,跟這個這個公式有關,是個複數。
光學上,折射率也跟這個這個公式有關,是個複數,虛數部分被叫做消散係數,用來度量隨指數形式衰減的情況...
...
真的是太多太多囉,只要是跟弦波有關,大概就逃不出這個公式的影響。
Python 程式:
既然尤拉公式這麼直接串連了三角函數,讓我們用它來算 SIn, Cos 囉。
假如我們有 x, y 兩個數字, Python 系統是直接支援 x**y 就 x的y次方的數值計算的。 (在其他語言系統下,被記為 x^y,或 pow(x,y))
而且如同前面所說的. Python 系統完全支援複數,所以 x, y 可以是複數。
所以根據尤拉公式,假如我們要計算 sin(1.234) 跟 cos(1.234) 的數值,其公式如下
2.718281828 ** (1.234 i) = cos(1.234) + i sin(1.234)
所以只要將 2.718281828 自然對數的底,把它用純虛數的 1.234 i 次方,這樣會得到一個複數,它的實數部分會是 cos(1.234) ,而它的虛數部分會是 sin(1.234)
所以, Cos(x) 可以這樣定義囉
def cos(x):
return (e**((1j)*x)).real # e 為 2.718281828
就計算 2.718281828 ** (j*x) 然後取實數部分.
Sin(x) 可以這樣定義
def sin(x):
return (e**((1j)*x)).imag # e 為 2.718281828
就計算 2.718281828 ** (j*x) 然後取虛數部分.
這樣就搞定囉,數學非常有趣吧。
就讓我們 import pyplot 模組,很快的把 sin(x), cos(x) 畫出來吧
x = [ float(x)*pi/50 for x in range(0, 100) ]
list comprehension, 利用 range(0, 100) 這個 0-100 的迭代器產生 0 - 100 之間的整數。 for-loop 至 x 後,float(x) 轉成浮點數乘上 pi/50,所以變成 0 - 2pi 之間總共 100點的 x 數據點
c = [ cos(xx) for xx in x ]
list comprehension, for-loop 利用 x 的 100點數據點算 cos 值
s = [ sin(xx) for xx in x ]
list comprehension, for-loop 利用 x 的 100點數據點算 sin 值
然後 plot()
漂亮的 sin(x) 跟 cos(x) 曲線就出現啦!
原始程式及結果
這邊用好用的 Jupyter Notebook 來產生漂亮的原始碼跟結果,並輸出成 html 貼入部落格文章中,放在下面就非常漂亮囉。
#
# sin(x) cos(x) by euler formula
#
# Frank Lin 2023.03.07
#
import matplotlib.pyplot as pyplot
e = 2.718281828
pi = 3.14159265358979
# cos(x)
def cos(x):
return (e**((1j)*x)).real
# sin(x)
def sin(x):
return (e**((1j)*x)).imag
# calculate data for plot
# List comprehension for x, cos(x), sin(x)
x = [ float(x)*pi/50 for x in range(0, 100) ]
c = [ cos(xx) for xx in x ]
s = [ sin(xx) for xx in x ]
# plot by pyplot
# plot data
pyplot.plot(x, s, 'c', label = 'sin(x)') # 'c' -> cyan color
pyplot.plot(x, c, 'y', label = 'cos(x)') # 'y' -> yellow color
# plot legend
pyplot.legend()
# show it
pyplot.show()
