Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cube root of negative numbers in a numpy array returns nan

Tags:

python

numpy

From Numpy documentation:

>>> a = np.arange(10)**3
>>> a
array([  0,   1,   8,  27,  64, 125, 216, 343, 512, 729])
>>> a[2]
8
>>> a[2:5]
array([ 8, 27, 64])
>>> a[:6:2] = -1000    # equivalent to a[0:6:2] = -1000; from start to position 6, exclusive, set every 2nd element to -1000
>>> a
array([-1000,     1, -1000,    27, -1000,   125,   216,   343,   512,   729])
>>> a[ : :-1]                                 # reversed a
array([  729,   512,   343,   216,   125, -1000,    27, -1000,     1, -1000])
>>> for i in a:
...     print(i**(1/3.))
...
nan
1.0
nan
3.0
nan
5.0
6.0
7.0
8.0
9.0

Could somebody explain me the last line of code? How does i to the power of 1/3 equal these numbers?

For example -1000^1/3 = nan? What part have I skipped over?

like image 574
user21398 Avatar asked Dec 07 '25 04:12

user21398


2 Answers

There is inbuilt function in numpy to find cuberoot. Check this out:

print(np.cbrt(a))

Your output will be :

[-10.   1. -10.   3. -10.   5.   6.   7.   8.   9.]
like image 54
Sapan Zaveri Avatar answered Dec 08 '25 16:12

Sapan Zaveri


In Python, (-1000)**(1/3.) returns a complex number,

>>> (-1000)**(1/3.)
(5+8.660254037844384j)

This happens because the way computer store numbers, 1/3 = 0.33333... is an irrational number which at some point gets approximated and therefore there is a loss in precision


>>> a = np.arange(10)**3
>>> a[:6:2] = -1000
>>> a
array([-1000,     1, -1000,    27, -1000,   125,   216,   343,   512,
         729], dtype=int32)
>>> for i in a:
     print((i)**(1/3.))


nan
1.0
nan
3.0
nan
4.999999999999999
5.999999999999999
6.999999999999999
7.999999999999999
8.999999999999998

Here the values in the ndarray a are of numpy.int32 type.
The code (i)**(1/3.) returns a result of type numpy.float64 since the second argument is a floating point.

>>> [type((i)**(1/3.)) for i in a]
[<class 'numpy.float64'>, <class 'numpy.float64'>, <class 'numpy.float64'>, <class 'numpy.float64'>, <class 'numpy.float64'>, <class 'numpy.float64'>, <class 'numpy.float64'>, <class 'numpy.float64'>, <class 'numpy.float64'>, <class 'numpy.float64'>]

(-1000)**(1/3.) is a complex number and cannot be stored as as numpy.float64 therefore nan


To avoid the nan you can change the dtype of the ndarray to numpy.complex and do the calculations

>>> b = a.astype(np.complex)
>>> b
array([-1000.+0.j,     1.+0.j, -1000.+0.j,    27.+0.j, -1000.+0.j,
         125.+0.j,   216.+0.j,   343.+0.j,   512.+0.j,   729.+0.j])

>>> for i in b:
     print((i)**(1/3.))


(4.999999999999999+8.660254037844384j)
(1+0j)
(4.999999999999999+8.660254037844384j)
(3+0j)
(4.999999999999999+8.660254037844384j)
(4.999999999999999+0j)
(5.999999999999999+0j)
(6.999999999999999+0j)
(7.999999999999999+0j)
(8.999999999999998+0j)

You can take the absolute values of these numbers using abs()

>>> for i in b:
     print(round(abs((i)**(1/3.))))


10.0
1.0
10.0
3.0
10.0
5.0
6.0
7.0
8.0
9.0
like image 36
Aniket Navlur Avatar answered Dec 08 '25 16:12

Aniket Navlur



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!