跳轉到

2.3 指數對數與三角恆等式#

本節目標#

  • 了解 SymPy 對指數律與對數律的自動化簡行為
  • 熟練 expand_log()、logcombine() 與 force 參數
  • 學會 powsimp()、powdenest() 處理冪次結構
  • 熟練三角恆等式工具:trigsimp()、expand_trig()
  • 體會 simplify(exp(I*pi)) 帶來的驚喜

從數學開始:指數、對數、三角的核心恆等式#

本章的核心恆等式:

\[ a^m a^n = a^{m+n}, \qquad \log(mn) = \log m + \log n \]
\[ \sin^2\theta + \cos^2\theta = 1, \qquad e^{i\pi} = -1 \]

但符號運算系統對這些式子的處理有微妙之處:在複數域上,某些「顯而易見」的等式其實不成立。例如 \(\log(xy) = \log x + \log y\) 對複數未必成立,甚至對負實數也不成立( \(\log((-1)(-1)) = 0\) ,但 \(\log(-1) + \log(-1) = 2\pi i\) )。這就是 SymPy 預設保守、需要 force 的原因。

指數律:冪次的自動合併#

SymPy 對乘法中的同底數冪會自動合併:

from sympy import symbols, exp, sqrt, simplify

x, y = symbols('x y')
print(x**2 * x**3)     # x**5(自動)
print(sqrt(2) * sqrt(6))  # 2*sqrt(3)(自動)

但冪的冪 \((a^m)^n = a^{mn}\) 預設不展開——因為在複數域上 \(n\) 非整數時可能出錯( \((x^2)^{1/2} \ne x\) 若 \(x<0\) ):

print((x**2)**(S(1)/2))   # 不展開,維持 sqrt(x**2)
print((x**2)**3)          # x**6(整數冪則自動展開)

powsimp 與 powdenest#

from sympy import powsimp, powdenest

n = symbols('n', positive=True)
print(powsimp(x**a * y**a))       # (x*y)**a(合併不同底的同次冪)
print(powdenest((x**a)**b))       # x**(a*b)(在適當假設下攤開)

對數:expand_log 與 logcombine#

對數的乘法律預設不會自動套用,因為需要「參數為正」的條件:

from sympy import log

print(log(x*y))    # log(x*y),不動
print(log(x) + log(y))  # log(x) + log(y),不動

expand_log():把 log 拆開#

a = symbols('a', positive=True)
b = symbols('b', positive=True)

print(expand_log(log(a*b)))        # log(a) + log(b)
print(expand_log(log(a**3)))       # 3*log(a)
print(expand_log(log(a/b)))        # log(a) - log(b)

注意:若變數沒有 positive 假設,expand_log() 會拒絕拆開:

print(expand_log(log(x*y)))        # log(x*y),因為 x 可能是負數

force 參數:強制套用#

若你確定變數在正數範圍(或只是想形式操作),可以加 force=True:

print(expand_log(log(x*y), force=True))   # log(x) + log(y)

logcombine():把 log 合併#

print(logcombine(log(x) + log(y)))        # 不動(無假設)
print(logcombine(log(a) + log(b)))        # log(a*b)(a, b 為正)
print(logcombine(log(x) + log(y), force=True))  # log(x*y)

三角恆等式:trigsimp 與 expand_trig#

trigsimp():化簡三角表達式#

from sympy import trigsimp, sin, cos, tan

print(trigsimp(sin(x)**2 + cos(x)**2))    # 1
print(trigsimp((2*tan(x)*cos(x)**2 - 1)/(1 + tan(x)**2)))
# -cos(x)**2
print(trigsimp(sin(x)/cos(x)))            # tan(x)?—— 看情況

expand_trig():展開三角函數#

expand_trig() 套用和角公式等,方向與 trigsimp() 相反:

from sympy import expand_trig

print(expand_trig(sin(x + y)))
# sin(x)*cos(y) + sin(y)*cos(x)

print(expand_trig(cos(2*x)))
# 2*cos(x)**2 - 1

print(expand_trig(tan(2*x)))
# 2*tan(x)/(1 - tan(x)**2)

驗證 \(\sin^2+\cos^2=1\)#

驗證恆等式的標準做法:做差、化簡、看是否為 0。

from sympy import simplify

print(simplify(sin(x)**2 + cos(x)**2 - 1))    # 0
print(trigsimp(sin(x)**2 + cos(x)**2 - 1))    # 0

也可以用 rewrite 換底再化簡:

from sympy import exp, I

expr = sin(x)**2 + cos(x)**2 - 1
print(simplify(expr.rewrite(exp)))   # 0(用歐拉公式改寫後化簡)

驚喜時刻:simplify(exp(I*pi)) = -1#

歐拉公式 \(e^{i\pi} = \cos\pi + i\sin\pi = -1\) 。在 SymPy 裡,這件事是自動發生的:

from sympy import exp, I, pi, simplify

print(exp(I*pi))         # -1(自動!)
print(exp(I*pi/2))       # I
print(exp(I*2*pi))       # 1
print(simplify(exp(I*pi) + 1))   # 0

因為 \(e^{i\theta}\) 對 \(\theta\) 為 \(\pi\) 的有理倍數時,SymPy 會直接用單位根的精確值化簡。這是符號系統「懂得數學」的漂亮展示。

動手實驗:驗證五個三角恆等式#

from sympy import (symbols, sin, cos, tan, sec, csc,
                   trigsimp, simplify, expand_trig)

x, y = symbols('x y', real=True)

# 恆等式 1:sin(2x) = 2 sin(x) cos(x)
lhs = expand_trig(sin(2*x))
rhs = 2*sin(x)*cos(x)
print(simplify(lhs - rhs))    # 0

# 恆等式 2:cos(2x) = cos^2(x) - sin^2(x)
lhs = expand_trig(cos(2*x))
rhs = cos(x)**2 - sin(x)**2
print(simplify(lhs - rhs))    # 0

# 恆等式 3:1 + tan^2(x) = sec^2(x)
expr = 1 + tan(x)**2 - sec(x)**2
print(trigsimp(expr))         # 0

# 恆等式 4:1 + cot^2(x) = csc^2(x)
expr = 1 + 1/tan(x)**2 - csc(x)**2
print(simplify(expr))         # 0

# 恆等式 5:sin(x + y) = sin x cos y + cos x sin y
lhs = expand_trig(sin(x + y))
rhs = sin(x)*cos(y) + cos(x)*sin(y)
print(simplify(lhs - rhs))    # 0

五個輸出都是 0,即五個恆等式全部驗證成功。

實驗延伸:

  1. 驗證和角公式 \(\cos(x+y) = \cos x\cos y - \sin x\sin y\) 。
  2. 對 trigsimp(1/tan(x)) 觀察結果——是 \(\cot(x)\) 還是別的形式?不同版本 SymPy 可能有差異。
  3. 試著不用 expand_trig,只用歐拉公式 rewrite(exp) 驗證 \(\sin(2x) = 2\sin x\cos x\) 。
  4. 檢驗 \(\log(xy) = \log x + \log y\) 在「無假設」「positive 假設」「force=True」三種情況下的行為差異。

小結與練習#

本節學會了:

  • SymPy 自動合併同底數冪的乘法,但不自動展開 \((a^m)^n\)
  • expand_log() 拆對數、logcombine() 合對數,正負號安全性由假設系統把關,必要時用 force=True
  • powsimp()、powdenest() 處理冪次結構
  • trigsimp() 化簡、expand_trig() 展開三角函數;驗證恆等式 = 做差化簡看是否為 0
  • exp(I*pi) 自動化為 \(-1\) ,歐拉公式深植於系統中

練習:

  1. 化簡 \(\frac{\sin^4 x - \cos^4 x}{\sin x - \cos x}\) ,並與 \(\sin x + \cos x\) 比對。
  2. 用 expand_log 與假設系統化簡 \(\log\left(\frac{a^2 b}{c}\right)\) (設 \(a,b,c\) 皆正)。
  3. 驗證半角公式 \(\sin^2\frac{x}{2} = \frac{1 - \cos x}{2}\) 。
  4. 計算 \(e^{i\pi/3}\) 、 \(e^{i\pi/6}\) 的精確值,並用 simplify 驗證 \(e^{i\theta}\) 的模長恆為 \(1\) 。