这是牛顿方程求解的简单代码,旨在找到复数根。
代码应该像这样工作:
导入库:代码导入 sympy 库来处理符号数学。
定义多项式:使用 sympy 库定义多项式方程 p(x)=x5+11x4−21x3−10x2−21x−5。
牛顿法函数:newton_method 函数实现牛顿法以在给定公差内查找函数的根。
求实根:它使用循环应用具有不同初始猜测的牛顿法来求多项式方程的实根。
减少多项式:reduce_polynomial 函数将多项式除以 (x−root) 以减少多项式的次数。
求复数根:利用获得的实根来约简多项式,并通过求解约简多项式来找到任意复数根。
输出:最后,它打印使用牛顿法和归约技术找到的实根和复根。
此代码利用牛顿法求实根,然后根据获得的实根简化多项式以求任意复数根。调整容差和初始猜测会影响不同多项式的方法的准确性和收敛性。
import sympy as sp
# Define the variable
x = sp.symbols('x')
# Define the polynomial
p = x**5 + 11*x**4 - 21*x**3 - 10*x**2 - 21*x - 5
# Find the real roots using Newton's method
tolerance = 1e-5 # Tolerance for approximation
roots = []
# Function for Newton's method
def newton_method(f, x0, tol, max_iter=100):
x = x0
iteration = 0
while iteration < max_iter:
x_next = x - f.subs(x, x) / f.diff(x).subs(x, x)
if abs(x - x_next) < tol:
return x_next
x = x_next
iteration += 1
return None
# Find real roots
for i in range(5):
root = newton_method(p, i, tolerance)
if root is not None:
roots.append(root)
print("Real roots:", roots)
# Reduce the polynomial to a lower degree
# This reduces the polynomial by dividing it by (x - root)
def reduce_polynomial(poly, root):
return sp.simplify(poly / (x - root))
# Find complex roots
complex_roots = []
for root in roots:
reduced_poly = reduce_polynomial(p, root)
complex_root = sp.solve(reduced_poly, x)
complex_roots.extend(complex_root)
print("Complex roots:", complex_roots)
**但是,我遇到了这个常见错误: **
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-3-beb367549ec5> in <cell line: 27>()
26 # Find real roots
27 for i in range(5):
---> 28 root = newton_method(p, i, tolerance)
29 if root is not None:
30 roots.append(root)
3 frames
<ipython-input-3-beb367549ec5> in newton_method(f, x0, tol, max_iter)
17 iteration = 0
18 while iteration < max_iter:
---> 19 x_next = x - f.subs(x, x) / f.diff(x).subs(x, x)
20 if abs(x - x_next) < tol:
21 return x_next
/usr/local/lib/python3.10/dist-packages/sympy/core/expr.py in diff(self, *symbols, **assumptions)
3584 def diff(self, *symbols, **assumptions):
3585 assumptions.setdefault("evaluate", True)
-> 3586 return _derivative_dispatch(self, *symbols, **assumptions)
3587
3588 ###########################################################################
/usr/local/lib/python3.10/dist-packages/sympy/core/function.py in _derivative_dispatch(expr, *variables, **kwargs)
1907 from sympy.tensor.array.array_derivatives import ArrayDerivative
1908 return ArrayDerivative(expr, *variables, **kwargs)
-> 1909 return Derivative(expr, *variables, **kwargs)
1910
1911
/usr/local/lib/python3.10/dist-packages/sympy/core/function.py in __new__(cls, expr, *variables, **kwargs)
1294 if isinstance(v, Integer):
1295 if i == 0:
-> 1296 raise ValueError("First variable cannot be a number: %i" % v)
1297 count = v
1298 prev, prevcount = variable_count[-1]
ValueError: First variable cannot be a number: 0```
I searched for value error in other post but problem unsolved.
x 是包含
sympy.symbol
的顶级变量,但在 newton_method
内部 x 被重新声明为包含浮点值 x = x0
的局部变量,因此它不再是符号,因此 f.subs(x, x)
无法工作,f.diff(x).subs(x, x)
也无法工作还有。
def newton_method(f, x0, tol, max_iter=100):
iteration = 0
while iteration < max_iter:
x_next = (x0 - f.subs(x, x0) / f.diff(x).subs(x, x0)).evalf()
if abs(x0 - x_next) < tol:
return x_next
x0 = x_next
iteration += 1
return None