27

I am trying to run a quadratic equation in python. However, it keeps on giving me a warning

RuntimeWarning: invalid value encountered in sqrt

Here's my code:

import numpy as np


a = 0.75 + (1.25 - 0.75)*np.random.randn(10000)
print(a)
b = 8 + (12 - 8)*np.random.randn(10000)
print(b)
c = -12 + 2*np.random.randn(10000)
print(c)
x0 = (-b - np.sqrt(b**2 - (4*a*c)))/(2 * a)
print(x0)
TrebledJ
  • 8,713
  • 7
  • 26
  • 48
Maroof G
  • 515
  • 1
  • 6
  • 15
  • As per the output of variables a,b and c and my sample calculation. I should not get a -ve number for the value of b**2 - (4*a*c). Nonetheless, it is giving out some 'nan' values. – Maroof G Aug 24 '16 at 12:54
  • There is a negative number with value `-3.1107176892482471` in `b**2 - (4*a*c)`. Actually, there are many – ham Aug 24 '16 at 12:57
  • @MaroofG You definitely have negative values. See my answer. – DeepSpace Aug 24 '16 at 13:00

4 Answers4

35

This is not 100% Python related. You can't calculate the square root of a negative number (when dealing with real numbers that is).

You didn't take any precautions for when b**2 - (4*a*c) is a negative number.

>>> import numpy as np
>>>
>>> np.sqrt(4)
2.0
>>> np.sqrt(-4)
__main__:1: RuntimeWarning: invalid value encountered in sqrt
nan

Let's test if you have negative values:

>>> import numpy as np
>>> 
>>> a = 0.75 + (1.25 - 0.75) * np.random.randn(10000)
>>> b = 8 + (12 - 8) * np.random.randn(10000)
>>> c = -12 + 2 * np.random.randn(10000)
>>> 
>>> z = b ** 2 - (4 * a * c)
>>> print len([_ for _ in z if _ < 0])
71
DeepSpace
  • 78,697
  • 11
  • 109
  • 154
  • 1
    Yup!!, it does generate -ve values. Thanks for pointing that out. I changed the random sample generator to "np.random.sample" and it works as expected. Appreciate your assistance DeepSpace and @dunder – Maroof G Aug 24 '16 at 13:19
10

Square roots are not defined for strictly negative real numbers, and numpy will produce nan for negative inputs of "real" dtype int, float, and it's two special values -np.inf and nan.

However, square roots are defined for all complex dtype:

Sign Data Type E.g. (x) np.sqrt(x) Runtime Warning
Float/Int 1. / 1 1. / 1
Complex 1+0J 1
Infinity np.inf np.inf
Float/Int -1. / -1 nan ⚠️
Complex -1+0j 1j
Infinity -np.inf nan ⚠️
N/A NaN np.nan nan
iacob
  • 20,084
  • 6
  • 92
  • 119
2

If you're hoping to do complex analysis (working with imaginary numbers as defined by sqrt(-1)) you can import cmath and use cmath.sqrt(-1) instead of numpy.sqrt(-1).

For example, when I'm calculating the refractive index of materials from permittivity and permeability (by definition, j is involved), I'll write functions in python as such:

def n(f):
    y = cmath.sqrt(mu1f(f) - j*mu2f(f)) * (e1f(f) - j*e2f(f))
    return y.real

Where e1f etc. are previously defined interpolating functions, all of which are a function of incident frequency f. The y resultant is, in it of itself, a complex value, the complex index of refraction, but I'm oftentimes only interested in the real portion (the refractive index) so that is what is returned.

Hope this helps

Michael Green
  • 719
  • 6
  • 15
1

I would like to add an insight along with the above answers. The cmath function always returns complex numbers but if you want a unified treatment of complex and float object I would recommend using numpy.lib.scimath.

Note: The sqrt() function in this is slower that that of the versions from cmath and math module but it has flexibility to return a complex object in the case of a negative argument and a float object otherwise

jick jack
  • 11
  • 2