・私には難しいです。以下、未確認です。
感想
・私には、同じに見えてきました。ChatGPT先生へ未確認です。
(本日の)ChatGPT先生へ
(# ver0.2 のソースコード 表示省略)
...
# 18*tan(I*(log(5) - 2*log(-2 - I))/2)
上のソースコードは、複素数で出力します。
下のソースコードは、複素数で出力しません。
違いを教えて下さい。
(# ver0.3 のソースコード 表示省略)
...
# 9
🔵 ver0.2 が複素数になる理由
...のように 複素対数形式の一般解 が出ます。
...
🔴 重要ポイント
θ を未知数にすると
・tan は周期関数
・逆関数は多価
・対数を使った複素一般解になる
という流れになります。
🟢 ver0.3 が実数になる理由
...
🔵 つまり ver0.3 は
・三角関数を含まない
・ただの有理式連立方程式
・完全に代数方程式
になっています。...という実数解が直接出ます。
🔬 なぜ positive=True でも複素になる?
...
三角関数の逆解は複素形式になるため、
positive 指定だけでは防げません。
...
ver0.2 を実数解だけにする方法 (深掘り)
✅ 方法①:solveset(..., domain=S.Reals) を使う(最も推奨)
・solve ではなく solveset を使います。
from sympy import *
x, y, θ = symbols('x y θ', positive=True)
PQ, PC = 4, 8
eqs = [
Eq(tan(θ), PC/y),
Eq(tan(2*θ), (PQ+PC)/x),
Eq(x*y, (PQ+PC)**2)
]
sol = solveset(
eqs[0].subs(y, solve(eqs[2], y)[0]), # 代入して1変数化
θ,
domain=S.Reals
)
print(sol)
✅ 方法②:solve(..., dict=True) + 実数フィルタ
from sympy import *
var('x θ y', positive=True)
PQ, PC = 4, 8
sol = solve([
Eq(tan(θ), PC/y),
Eq(tan(2*θ), (PQ+PC)/x),
Eq(x*y, (PQ+PC)**2)
], [x, y, θ], dict=True)
# 実数解のみ抽出
real_sol = [
s for s in sol
if all(val.is_real for val in s.values())
]
print(real_sol)
✅ 方法③:rewrite(sin,cos) + simplify
from sympy import *
# --- 変数定義 ---
x, y = symbols('x y', positive=True)
θ = symbols('θ', real=True)
PQ, PC = 4, 8
S = PQ + PC # 12
# --- tan を sin/cos に変換 ---
eq1 = Eq(sin(θ)/cos(θ), PC/y)
# tan(2θ) を公式で直接展開(ここが重要)
# tan(2θ) = 2 sinθ cosθ / (cos²θ - sin²θ)
eq2 = Eq(
2*sin(θ)*cos(θ)/(cos(θ)**2 - sin(θ)**2),
S/x
)
eq3 = Eq(x*y, S**2)
# --- sinθ, cosθ を未知数に置き換える ---
s, c = symbols('s c', real=True)
eq1 = eq1.subs({sin(θ): s, cos(θ): c})
eq2 = eq2.subs({sin(θ): s, cos(θ): c})
# --- 単位円条件を追加 ---
eq4 = Eq(s**2 + c**2, 1)
# --- 連立を解く ---
sol = solve([eq1, eq2, eq3, eq4], [x, y, s, c], dict=True)
# --- 実数解のみ抽出 ---
real_sol = [
soln for soln in sol
if all(val.is_real for val in soln.values())
]
print(real_sol)
✅ 方法④(最も安定):事前に θ の範囲を指定する
from sympy import *
# 記号定義
x = symbols('x', positive=True)
y = symbols('y', positive=True)
θ = symbols('θ', real=True) # ← real指定が重要
PQ, PC = 4, 8
# 方程式
eq1 = Eq(tan(θ), PC/y)
eq2 = Eq(tan(2*θ), (PQ+PC)/x)
eq3 = Eq(x*y, (PQ+PC)**2)
# まず solve で一般解を取得
sol = solve([eq1, eq2, eq3], [x, y, θ], dict=True)
# 実数かつ 0 < θ < pi/2 を満たす解のみ抽出
real_sol = []
for s in sol:
θ_val = s[θ]
if θ_val.is_real:
θ_num = N(θ_val)
if 0 < θ_num < pi/2:
real_sol.append({
x: N(s[x]),
y: N(s[y]),
θ: θ_num
})
print(real_sol)
[{x: 9.00000000000000,
y: 16.0000000000000,
θ: 0.463647609000806}]
どれを深掘りますか?
???
いつもと違うおすすめです。
Qiita 内
sympy のdoc
✅ 方法①:solveset(..., domain=S.Reals) を使う(最も推奨)
