[SciPy-User] Numerical precision: Scipy Vs Numpy
Evgeni Burovski
evgeny.burovskiy at gmail.com
Wed Nov 4 08:11:12 EST 2015
On Wed, Nov 4, 2015 at 12:58 PM, Sergio Rojas <sergio_r at mail.com> wrote:
> """
> Having fun with numerical precision/errors, a solution of the quadratic
> equation [a*x**2 + b*x + c == 0] with small values for the
> constant a is given an unexpected result when comparing
> SciPy and SymPy numerical results, which I hope an earthly kind soul could
> explain. The output is as follows (the bothering result
> is on the second root property):
>
> SciPy
> a*x1**2 + b*x1 + c = 16777217.0
> a*x2**2 + b*x2 + c = 1.11022302463e-16
> Root properties:
> (x1 + x2) + b/a = 0.0
> x1*x2 - c/a = 0.0
> ----
> SymPy
> a*x1**2 + b*x1 + c = 16777217.0000000
> a*x2**2 + b*x2 + c = 0
> Root properties:
> (x1 + x2) + b/a = 0
> x1*x2 - c/a = 0.125000000000000
> """
>
> import scipy
>
> def myprint(a, b, c, x1, x2):
> print('a*x1**2 + b*x1 + c = '),
> print(a*x1**2 + b*x1 + c)
> print('a*x2**2 + b*x2 + c = '),
> print(a*x2**2 + b*x2 + c)
> print("\t Root properties: ")
> print('(x1 + x2) + b/a = '),
> print((x1+x2) + float(b)/float(a))
> print(' x1*x2 - c/a = '),
> print(x1*x2 - float(c)/float(a))
>
> a = 1.0e-15
> b = 10000.0
> c = 1.0
>
> coeff = [a, b, c]
> x1, x2 = scipy.roots(coeff)
>
> print("\t SciPy ")
> myprint(a, b, c, x1, x2)
>
> from sympy import *
> var('x')
> x1, x2 = solve(a*x**2 + b*x + c, x)
>
> print(" \t ---- \n \t SymPy ")
> myprint(a, b, c, x1, x2)
>
> # Thanks in advance,
> # Sergio
> _______________________________________________
> SciPy-User mailing list
> SciPy-User at scipy.org
> https://mail.scipy.org/mailman/listinfo/scipy-user
This is a catastrophic loss of precision.
For a way out, see, for example,
http://math.stackexchange.com/questions/866331/how-to-implement-a-numerically-stable-solution-of-a-quadratic-equation
Demo:
In [1]: a, b, c = 1e-15, 1e4, 1.0
In [2]: D = b**2 - 4.*a*c
In [3]: import numpy as np
In [4]: 2.*c / (-b - np.sqrt(D))
Out[4]: -0.0001
In [5]: import sympy as sy
In [6]: x = sy.var('x')
In [7]: sy.solve(a*x**2 + b*x + c)
Out[7]: [-1.00000000000000e+19, -0.000100000000000000]
More information about the SciPy-User
mailing list