求方程组的根,精确到任意小数精度
Find roots of a system of equations to an arbitrary decimal precision
给定值数组 x
的初始猜测,我试图找到最接近 x
的系统的根。如果您熟悉求系统的根,您就会明白,求方程组的根 f
满足:
0 = f_1(x)
0 = f_2(x)
....
0 = f_n(x)
其中 f_i
是 f
中的一个特定函数
scipy
中有一个包可以做到这一点:scipy.optimize.newton_krylov
。例如:
import scipy.optimize as sp
def f(x):
f0 = (x[0]**2) + (3*(x[1]**3)) - 2
f1 = x[0] * (x[1]**2)
return [f0, f1]
# Nearest root is [sqrt(2), 0]
print sp.newton_krylov(f, [2, .01], iter=100, f_tol=Dc('1e-15'))
>>> [ 1.41421356e+00 3.49544535e-10] # Close enough!
但是,我在 python 中使用 decimal
包,因为我的工作非常精确。 decimal
提供比普通小数精度更高的精度。 scipy.optimize.newton_krylov
returns 浮点精度值。有没有办法以任意精确的小数精度得到我的答案?
您可以尝试复制代码并由 scipy.optimize.newton_krylov
引用,然后修改它以使用 decimal
值而不是浮点值。当然,这可能既困难又费时。
我在其他情况下也做过同样的事情,但从来没有像这样。
我找到了针对相同问题的 mpmath
module, which contains mpmath.findroot
. mpmath
uses arbitrary decimal-point precision for all of its numbers. mpmath.findroot
will find the nearest root within tolerance. Here is an example of using mpmath
,精度更高:
import scipy.optimize as sp
import mpmath
from mpmath import mpf
mpmath.mp.dps = 15
def mp_f(x1, x2):
f1 = (x1**2) + (3*(x2**3)) - 2
f2 = x1 * (x2**2)
return f1, f2
def f(x):
f0 = (x[0]**2) + (3*(x[1]**3)) - 2
f1 = x[0] * (x[1]**2)
return [f0, f1]
tmp_solution = sp.newton_krylov(f, [2, .01], f_tol=Dc('1e-10'))
print tmp_solution
>>> [ 1.41421356e+00 4.87315249e-06]
for _ in range(8):
tmp_solution = mpmath.findroot(mp_f, (tmp_solution[0], tmp_solution[1]))
print tmp_solution
mpmath.mp.dps += 10 # Increase precision
>>> [ 1.4142135623731]
[4.76620313173184e-9]
>>> [ 1.414213562373095048801689]
[4.654573673348783724565804e-12]
>>> [ 1.4142135623730950488016887242096981]
[4.5454827012374811707063801808968925e-15]
>>> [ 1.41421356237309504880168872420969807856967188]
[4.43894795688326535096068850443292395286770757e-18]
>>> [ 1.414213562373095048801688724209698078569671875376948073]
[4.334910114213471839327827177504976152074382061299675453e-21]
>>> [ 1.414213562373095048801688724209698078569671875376948073176679738]
[4.2333106584123451747941381835420647823192649980317402073699554127e-24]
>>> [ 1.41421356237309504880168872420969807856967187537694807317667973799073247846]
[4.1340924398558139440207202654766836515453497962889870471467483995909717197e-27]
>>> [ 1.41421356237309504880168872420969807856967187537694807317667973799073247846210703885]
[4.037199648296693366576484784520203892002447351324378380584214947262318103197216393589e-30]
精度可以任意提高。
给定值数组 x
的初始猜测,我试图找到最接近 x
的系统的根。如果您熟悉求系统的根,您就会明白,求方程组的根 f
满足:
0 = f_1(x)
0 = f_2(x)
....
0 = f_n(x)
其中 f_i
是 f
scipy
中有一个包可以做到这一点:scipy.optimize.newton_krylov
。例如:
import scipy.optimize as sp
def f(x):
f0 = (x[0]**2) + (3*(x[1]**3)) - 2
f1 = x[0] * (x[1]**2)
return [f0, f1]
# Nearest root is [sqrt(2), 0]
print sp.newton_krylov(f, [2, .01], iter=100, f_tol=Dc('1e-15'))
>>> [ 1.41421356e+00 3.49544535e-10] # Close enough!
但是,我在 python 中使用 decimal
包,因为我的工作非常精确。 decimal
提供比普通小数精度更高的精度。 scipy.optimize.newton_krylov
returns 浮点精度值。有没有办法以任意精确的小数精度得到我的答案?
您可以尝试复制代码并由 scipy.optimize.newton_krylov
引用,然后修改它以使用 decimal
值而不是浮点值。当然,这可能既困难又费时。
我在其他情况下也做过同样的事情,但从来没有像这样。
我找到了针对相同问题的 mpmath
module, which contains mpmath.findroot
. mpmath
uses arbitrary decimal-point precision for all of its numbers. mpmath.findroot
will find the nearest root within tolerance. Here is an example of using mpmath
,精度更高:
import scipy.optimize as sp
import mpmath
from mpmath import mpf
mpmath.mp.dps = 15
def mp_f(x1, x2):
f1 = (x1**2) + (3*(x2**3)) - 2
f2 = x1 * (x2**2)
return f1, f2
def f(x):
f0 = (x[0]**2) + (3*(x[1]**3)) - 2
f1 = x[0] * (x[1]**2)
return [f0, f1]
tmp_solution = sp.newton_krylov(f, [2, .01], f_tol=Dc('1e-10'))
print tmp_solution
>>> [ 1.41421356e+00 4.87315249e-06]
for _ in range(8):
tmp_solution = mpmath.findroot(mp_f, (tmp_solution[0], tmp_solution[1]))
print tmp_solution
mpmath.mp.dps += 10 # Increase precision
>>> [ 1.4142135623731]
[4.76620313173184e-9]
>>> [ 1.414213562373095048801689]
[4.654573673348783724565804e-12]
>>> [ 1.4142135623730950488016887242096981]
[4.5454827012374811707063801808968925e-15]
>>> [ 1.41421356237309504880168872420969807856967188]
[4.43894795688326535096068850443292395286770757e-18]
>>> [ 1.414213562373095048801688724209698078569671875376948073]
[4.334910114213471839327827177504976152074382061299675453e-21]
>>> [ 1.414213562373095048801688724209698078569671875376948073176679738]
[4.2333106584123451747941381835420647823192649980317402073699554127e-24]
>>> [ 1.41421356237309504880168872420969807856967187537694807317667973799073247846]
[4.1340924398558139440207202654766836515453497962889870471467483995909717197e-27]
>>> [ 1.41421356237309504880168872420969807856967187537694807317667973799073247846210703885]
[4.037199648296693366576484784520203892002447351324378380584214947262318103197216393589e-30]
精度可以任意提高。