跳轉到

3.3 不等式與區間#

本節目標#

  • 學會用 solve_univariate_inequality() 解一元不等式,用 reduce_inequalities() 處理多條件。
  • 認識 Interval 區間物件與集合運算(交集、聯集)。
  • 理解解集合的表示:FiniteSet、Interval、Union、ConditionSet。
  • 掌握含絕對值、分母的不等式的注意事項(分母不為零、開閉區間)。
  • 實驗:畫出 \(f(x) > 0\) 的解區間,與函數圖形互相印證。

數學概念:不等式的解是集合#

等式的解通常是有限個點;不等式

\[ f(x) > 0 \]

的解通常是一個或數個區間。解不等式的標準流程(手算):

  1. 找出「臨界點」: \(f(x) = 0\) 的根與 \(f(x)\) 無定義的點(分母為零處)。
  2. 這些臨界點把實數軸切成若干段。
  3. 在每段中取測試點判斷 \(f\) 的正負(符號表法)。
  4. 依不等號決定端點的開閉: \(\geq\) 含根(閉)、 \(>\) 不含根(開);無定義點一律開。

例:解 \(x^2 - 4 > 0\) 。臨界點 \(x = \pm 2\) ,符號表顯示在 \((-\infty, -2)\) 與 \((2, \infty)\) 為正,故解集為

\[ (-\infty, -2) \cup (2, \infty) \]

solve_univariate_inequality#

from sympy import symbols, solve_univariate_inequality, S, oo

x = symbols('x', real=True)   # 不等式在實數域上討論

# 例 1:x^2 - 4 > 0
r1 = solve_univariate_inequality(x**2 - 4 > 0, x)
print(r1)                     # Union(Interval.open(-oo, -2), Interval.open(2, oo))
print(r1.as_set())            # 同上,明確轉成集合

# 例 2:x^2 - 4 <= 0(含等號 → 閉區間)
print(solve_univariate_inequality(x**2 - 4 <= 0, x))   # Interval(-2, 2)

# 例 3:一次不等式 2x - 3 >= 1
print(solve_univariate_inequality(2*x - 3 >= 1, x))    # Interval(2, oo)

# 例 4:嚴格不等式回傳開區間, relational 物件也可取得
sol = solve_univariate_inequality(x**2 < 9, x, relational=False)
print(sol)                    # Interval.open(-3, 3)

注意:宣告 x = symbols('x', real=True) 很重要——不等式只對實數有意義,先聲明變數的假設可避免 SymPy 嘗試複數域。

reduce_inequalities:多條件聯立#

多個不等式(或混合等式)要「同時成立」,就是取交集:

from sympy import symbols, reduce_inequalities, And, solve

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

# 例 1:-1 < x < 5 且 x^2 >= 4 → 條件的交集
print(reduce_inequalities([-1 < x, x < 5, x**2 >= 4], x))
# Union(Interval(-2 ... ), ...) 視化簡結果

# 例 2:分式不等式 (x-1)/(x+2) > 0
# 手算:分子分母各找零點 -2, 1;符號表 → x < -2 或 x > 1
print(reduce_inequalities((x - 1)/(x + 2) > 0, x))
# Union(Interval.open(-oo, -2), Interval.open(1, oo))  ← -2 自動排除!

# 例 3:混合等式與不等式:x + y = 3 且 x > 0(兩變數)
y = symbols('y', real=True)
print(reduce_inequalities([x + y - 3, x > 0], x))
# (0, oo) → 因 y = 3 - x,條件只剩 x > 0

# 例 4:絕對值不等式 |x - 3| < 2
from sympy import Abs
print(reduce_inequalities(Abs(x - 3) < 2, x))   # (1 < x) & (x < 5) 即 Interval.open(1, 5)

reduce_inequalities 比 solve_univariate_inequality 更通用:可處理多變數、混合等式,輸出常是 And/Or 的邏輯組合,用 .as_set() 可轉成區間集合。

Interval 物件與集合運算#

from sympy import Interval, Union, S, oo, symbols, EmptySet

# 四種區間
print(Interval(1, 3))          # [1, 3]        閉區間
print(Interval.open(1, 3))     # (1, 3)        開區間
print(Interval.Lopen(1, 3))    # (1, 3]        左開右閉
print(Interval.Ropen(1, 3))    # [1, 3)        左閉右開
print(Interval(-oo, 2))        # (-oo, 2]      無窮區間(oo = ∞)

# 集合運算
A = Interval(0, 5)
B = Interval.open(3, 8)
print(A.intersect(B))          # Interval.Lopen(3, 5)  即 (3, 5]
print(A.union(B))              # [0, 8)
print(A - B)                   # 差集 [0, 3]
print(Interval(0, 1).intersect(Interval(2, 3)))   # EmptySet

# 判斷歸屬
print(2.5 in B)                # True
print(S(3) in B)               # False(開區間不含 3)

# 與解集合結合:把解的邏輯條件轉為集合再操作
x = symbols('x', real=True)
s1 = (x**2 - 4 > 0).as_set()   # 需要 assume real
print(s1)                      # Union(Interval.open(-oo, -2), Interval.open(2, oo))

幾何直覺:不等式的解集是數線上的「陰影區域」,Interval 與 Union 就是把陰影精確記錄下來的資料結構;交集對應「同時滿足兩條件」,聯集對應「滿足任一條件」。

解集合的表示:ConditionSet#

當 SymPy 無法化簡解集合時,它不會放棄,而是給一個「條件集合」——用描述法寫出的集合:

from sympy import symbols, solveset, S, ConditionSet, sin

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

# solveset 回傳的永遠是集合
print(solveset(x**2 - 4, x, domain=S.Reals))
# {-2, 2}          FiniteSet

print(solveset(sin(x), x, domain=S.Reals))
# ImageSet(Lambda(n, 2*n*pi), Integers) ∪ ImageSet(Lambda(n, 2*n*pi + pi), Integers)
# ← 無限多解:x = 2nπ 與 x = 2nπ + π(n ∈ ℤ),用映射表示

print(solveset(x**2 + x + 1, x, domain=S.Reals))
# EmptySet         ← 判別式 < 0,實數域無解

# ConditionSet 的樣子:transcendental方程解不出來時
cset = solveset(sin(x) - x, x, domain=S.Reals)
print(cset)
# ConditionSet(x, Eq(sin(x) - x, 0), Reals)
# 讀法:「使 sin(x) - x = 0 的所有實數 x」——正確但未化簡

ConditionSet 的意義:解集合的描述法 \(\{x \in \mathbb{R} : \sin x - x = 0\}\) 。它保證答案的正確語義,即使演算法找不到閉式解。這類方程就要靠 3.4 節的數值方法。

含絕對值/分母的不等式:注意事項#

from sympy import symbols, reduce_inequalities, Abs, solve_univariate_inequality

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

# 1. 絕對值不等式:|2x - 1| <= 5 → -5 <= 2x-1 <= 5 → -2 <= x <= 3
print(reduce_inequalities(Abs(2*x - 1) <= 5, x))   # -2 <= x, x <= 3

# 2. 分母不允許為零:1/x > 0
print(reduce_inequalities(1/x > 0, x))             # (0, oo) 開區間,0 被排除
print(reduce_inequalities(1/x >= 0, x))            # (0, oo) ← 依然不含 0!
# 關鍵:≥ 的「=」只在 f(x)=0 有定義處生效;分母零點永遠是開的

# 3. 危險陷阱:兩邊同乘 x 不等價!(x 的正負會翻轉不等號)
# 錯誤做法:x*(1/x) > 0*x → 1 > 0 恆真 ✗
# 正確做法:通分或分區間討論,交給 SymPy:
print(reduce_inequalities((x - 2)/x > 0, x))
# Union(Interval.open(-oo, 0), Interval.open(2, oo))

# 4. 根號不等式:sqrt(x) < 2,需兼顧定義域 x >= 0
from sympy import sqrt
print(reduce_inequalities(sqrt(x) < 2, x))         # [0, 4) ← 左端是閉(定義域)

三條鐵律:

  1. 分母零點永遠開,不論不等號是否有等號。
  2. 不等式兩邊不可隨意乘以含未知數的式子(會翻轉方向或產生偽解)。
  3. 定義域優先:根號、對數、分母都會限制解的範圍,SymPy 會自動處理,手算時要記得。

動手實驗:畫出 \(f(x) > 0\) 的解區間#

實驗目標:解出 \(f(x) = x^3 - 3x = x(x-\sqrt{3})(x+\sqrt{3})\) 大於 0 的區間,並用符號表 + 簡易畫圖印證。

from sympy import symbols, solve, reduce_inequalities, plot, Rational

x = symbols('x', real=True)
f = x**3 - 3*x

# 1. 臨界點
crit = sorted(solve(f, x), key=lambda r: float(r))
print(crit)                   # [-sqrt(3), 0, sqrt(3)]

# 2. 解不等式
sol = (f > 0).as_set()
print(sol)
# Union(Interval.open(-sqrt(3), 0), Interval.open(sqrt(3), oo))

# 3. 符號表:在每段取測試點
import itertools
pts = [-2, -1, Rational(1,2), 2]     # 各段的測試點
for p in pts:
    print(f"f({float(p):+.2f}) = {float(f.subs(x, p)):+.2f}")
# -2.36 -, +0.66 +, -1.38 -, +2.00 +  → 與解集一致(正的區段即解)

# 4. 畫圖目視(細節見第 X 章 plot 篇;先嘗試執行)
p1 = plot(f, (x, -3, 3), line_color='blue', show=False)
p1.show()   # 觀察 f > 0 的位置是否正是 (-√3, 0) 與 (√3, ∞)

實驗觀察:

  1. 三次曲線在根之間「正負交替」(單根處必變號),所以 \(f>0\) 的解是根之間的交替區段。
  2. 若把 \(f\) 改成 \(x^3 - 3x^2 = x^2(x-3)\) , \(x=0\) 是偶數重根,曲線不變號——解集變成 \((3, \infty)\) ,0 處 \(f=0\) 也不屬於 \(f>0\) 。動手驗證:
g = x**3 - 3*x**2
print((g > 0).as_set())       # Interval.open(3, oo)
print((g >= 0).as_set())      # {0} ∪ [3, oo)  ← 0 是孤立點!

進一步挑戰:

  1. 解 \(\frac{x^2 - 1}{x + 2} \leq 0\) ,並用符號表逐段驗證(注意 \(x = -2\) 必須排除)。
  2. 解 \(|x^2 - 4| > 1\) ,把結果畫在數線示意圖上(用 Interval 列印即可)。
  3. 對 \(f(x) = \sin x\) ( \(x \in [0, 2\pi]\) ),用 solveset(sin(x) > 0, x, domain=Interval(0, 2*pi)) 求解並畫圖印證。

小結與練習#

小結

  • 不等式的解是集合:Interval(區間)、FiniteSet(點)、Union(聯集)、EmptySet、ConditionSet(描述法)。
  • solve_univariate_inequality() 解單變數不等式;reduce_inequalities() 處理多條件與混合等式;.as_set() 把邏輯條件轉為集合。
  • 分母零點永遠排除;等號只在函數有定義的零點生效;定義域(根號、對數)會收縮解集。
  • 臨界點 + 符號表是手算與程式共同的骨架;重根處函數可能不變號,解集會出現孤立點。

練習

  1. 解 \(x^2 - 2x - 3 \geq 0\) ,寫出精確的區間聯集,並說明每個端點為何是閉的。
  2. 解 \(\frac{2x - 1}{x - 3} < 1\) (先移項通分再解,避免直接交叉相乘)。
  3. 解 \(|x + 1| + |x - 2| \leq 5\) ,與手算的分段討論對照。
  4. 求 \(\sqrt{x + 1} - \sqrt{x} > \frac{1}{2}\) 的解集(存在嗎?用 reduce_inequalities 驗證你的手算結論)。
  5. 對 \(f(x) = x^4 - 5x^2 + 4\) ,用「臨界點 + 符號表 + .as_set()」三步驟解 \(f(x) > 0\) ,並用 plot 目視確認。