SymPy solve结果无法用于np.isclose:ufunc 'isfinite'不支持错误排查
解决SymPy解与np.isclose不兼容的问题
问题根源
SymPy的solve()函数返回的解是包含SymPy符号/数值对象(如sympy.Float、sympy.Integer)的元组,而np.isclose()仅支持Python原生数值类型(int/float)或numpy数值类型,直接传入SymPy对象会触发TypeError: ufunc 'isfinite' not supported...错误。
解决方案
方案1:将SymPy解转换为原生数值类型
遍历solve()返回的解,把每个分量用float()或int()转换为Python原生数值,之后即可正常使用np.isclose()。
示例代码:
import sympy as sp import numpy as np r = 5 x0, y0 = 3, 4 k = -3/4 x, y = sp.symbols('x y') circle_eq = x**2 + y**2 - r**2 line_eq = y - y0 - k*(x - x0) # 求解方程组 solutions = sp.solve((circle_eq, line_eq), (x, y)) # 转换为Python原生数值元组 numeric_solutions = [(float(sol[0]), float(sol[1])) for sol in solutions] # 筛选已知点,获取另一个交点 other_point = None for sol in numeric_solutions: if np.isclose(sol[0], x0, rel_tol=1e-9) and np.isclose(sol[1], y0, rel_tol=1e-9): continue other_point = sol print(other_point)
方案2:使用SymPy原生的近似比较函数
SymPy 1.7及以上版本提供了isclose()函数,可直接对SymPy对象进行近似比较,无需转换类型。如果后续需要数值结果,再按需转换为原生类型。
示例代码:
import sympy as sp from sympy import isclose r = 5 x0, y0 = 3, 4 k = -3/4 x, y = sp.symbols('x y') circle_eq = x**2 + y**2 - r**2 line_eq = y - y0 - k*(x - x0) solutions = sp.solve((circle_eq, line_eq), (x, y)) other_point = None for sol in solutions: if isclose(sol[0], x0, rel_tol=1e-9) and isclose(sol[1], y0, rel_tol=1e-9): continue other_point = sol # 如需数值结果,转换为float other_point_numeric = (float(other_point[0]), float(other_point[1])) print(other_point_numeric)
特殊情况:符号解需先代入数值
如果方程组中存在未赋值的符号变量(比如r是符号而非具体数值),需先通过subs()替换变量为具体值,再进行转换或比较:
import sympy as sp r_sym = sp.symbols('r') x0, y0 = 3, 4 k = -3/4 x, y = sp.symbols('x y') circle_eq = x**2 + y**2 - r_sym**2 line_eq = y - y0 - k*(x - x0) solutions = sp.solve((circle_eq, line_eq), (x, y)) # 代入r=5的数值 substituted_sols = [(sol[0].subs(r_sym, 5), sol[1].subs(r_sym, 5)) for sol in solutions] # 后续操作同方案1或方案2
内容的提问来源于stack exchange,提问作者Cuteufo
相关产品推荐
相关产品推荐

