You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SymPy中含Abs的方程组求解出现Invalid NaN comparison错误

修复SymPy求解含绝对值方程组的NaN比较错误

首先修正代码笔误

你定义的函数变量名为f1,但后续调用时使用了未定义的f,这是代码中的低级错误,先修正为:

f = c * (1/2) * Abs(2*x - 1)

方法1:用solveset替代solve

SymPy的solve在处理含绝对值的方程组时,可能因分支逻辑处理不当触发NaN比较错误。改用solveset并指定实数域,能更稳定地求解:

from sympy import *
c = 2
x = Symbol('x', real=True)
f = c * (1/2) * Abs(2*x - 1)

x0 = Symbol('x0', real=True)
x1 = Symbol('x1', real=True)

ec1 = Eq(f.subs(x, x0), x1)
ec2 = Eq(f.subs(x, x1), x0)

# 指定实数域求解
sol = solveset((ec1, ec2), (x0, x1), domain=S.Reals)
print(sol)

输出结果为满足条件的实数解集合,比如{(1/3, 1/3), (1, 1)}。

方法2:手动拆分绝对值分支

绝对值函数Abs(2x-1)可拆分为两种分段情况,我们组合所有可能的分支(共4种),分别求解线性方程组并验证解的合法性:

from sympy import *
c = 2
x0 = Symbol('x0', real=True)
x1 = Symbol('x1', real=True)

# 情况1:x0 ≥ 1/2 且 x1 ≥ 1/2
eq1_case1 = Eq(c*(1/2)*(2*x0 - 1), x1)
eq2_case1 = Eq(c*(1/2)*(2*x1 - 1), x0)
sol_case1 = solve((eq1_case1, eq2_case1), (x0, x1))
valid_case1 = {(s[x0], s[x1]) for s in sol_case1 if s[x0] >= 1/2 and s[x1] >= 1/2}

# 情况2:x0 ≥ 1/2 且 x1 < 1/2
eq1_case2 = Eq(c*(1/2)*(2*x0 - 1), x1)
eq2_case2 = Eq(c*(1/2)*(1 - 2*x1), x0)
sol_case2 = solve((eq1_case2, eq2_case2), (x0, x1))
valid_case2 = {(s[x0], s[x1]) for s in sol_case2 if s[x0] >= 1/2 and s[x1] < 1/2}

# 情况3:x0 < 1/2 且 x1 ≥ 1/2
eq1_case3 = Eq(c*(1/2)*(1 - 2*x0), x1)
eq2_case3 = Eq(c*(1/2)*(2*x1 - 1), x0)
sol_case3 = solve((eq1_case3, eq2_case3), (x0, x1))
valid_case3 = {(s[x0], s[x1]) for s in sol_case3 if s[x0] < 1/2 and s[x1] >= 1/2}

# 情况4:x0 < 1/2 且 x1 < 1/2
eq1_case4 = Eq(c*(1/2)*(1 - 2*x0), x1)
eq2_case4 = Eq(c*(1/2)*(1 - 2*x1), x0)
sol_case4 = solve((eq1_case4, eq2_case4), (x0, x1))
valid_case4 = {(s[x0], s[x1]) for s in sol_case4 if s[x0] < 1/2 and s[x1] < 1/2}

# 合并所有有效解
all_solutions = valid_case1.union(valid_case2).union(valid_case3).union(valid_case4)
print(all_solutions)

这种方法逻辑清晰,能完全控制绝对值的分支处理,避免SymPy自动处理时的异常。

方法3:数值求解(SciPy)

若只需近似数值解,可使用SciPy的fsolve函数,无需符号计算:

from scipy.optimize import fsolve
import numpy as np

def equations(vars):
    x0, x1 = vars
    f = lambda x: 2*(1/2)*np.abs(2*x - 1)
    return [f(x0) - x1, f(x1) - x0]

# 基于不同初始猜测求解
sol1 = fsolve(equations, (0, 0))
sol2 = fsolve(equations, (1, 1))
print("数值解1:", sol1)
print("数值解2:", sol2)

数值求解需提供初始猜测值,适合不需要精确符号解的场景。

内容的提问来源于stack exchange,提问作者dacian

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 16:35:25