0

I have two numpy arrays of shape (1, 250000):

a = [[  0 254   1 ..., 255   0   1]]
b = [[  1   0 252 ...,   0 255 255]]

I want to create a new numpy array whose elements are the square root of the sum of squares of elements in the arrays a and b, but I am not getting the correct result:

>>> c = np.sqrt(np.square(a)+np.square(b))
>>> print c
[[ 1.          2.          4.12310553 ...,  1.          1.          1.41421354]]

Am I missing something simple here?

3
  • 1
    your example actually works fine for me. import numpy as np a = [[ 0 ,254 , 1, 255, 0 , 1]] b = [[ 1 , 0, 252 , 0, 255, 255]] c = np.sqrt(np.square(a)+np.square(b)) Output: [[ 1. 254. 252.00198412 255. 255. 255.00196078]] The extra square brackets are not needed, but I left them in place to show your code runs, at least with a short example. Commented Apr 8, 2016 at 4:45
  • 2
    Please always provide an executable example if you can (see minimal reproducible example) to allow people to run your problem right away. Commented Apr 8, 2016 at 4:46
  • Thank you for the feedback! Commented Apr 8, 2016 at 15:47

2 Answers 2

7

Presumably your arrays a and b are arrays of unsigned 8 bit integers--you can check by inspecting the attribute a.dtype. When you square them, the data type is preserved, and the 8 bit values overflow, which means the values "wrap around" (i.e. the squared values are modulo 256):

In [7]: a = np.array([[0, 254, 1, 255, 0, 1]], dtype=np.uint8)

In [8]: np.square(a)
Out[8]: array([[0, 4, 1, 1, 0, 1]], dtype=uint8)

In [9]: b = np.array([[1, 0, 252, 0, 255, 255]], dtype=np.uint8)

In [10]: np.square(a) + np.square(b)
Out[10]: array([[ 1,  4, 17,  1,  1,  2]], dtype=uint8)

In [11]: np.sqrt(np.square(a) + np.square(b))
Out[11]: 
array([[ 1.        ,  2.        ,  4.12310553,  1.        ,  1.        ,
         1.41421354]], dtype=float32)

To avoid the problem, you can tell np.square to use a floating point data type:

In [15]: np.sqrt(np.square(a, dtype=np.float64) + np.square(b, dtype=np.float64))
Out[15]: 
array([[   1.        ,  254.        ,  252.00198412,  255.        ,
         255.        ,  255.00196078]])

You could also use the function numpy.hypot, but you might still want to use the dtype argument, otherwise the default data type is np.float16:

In [16]: np.hypot(a, b)
Out[16]: array([[   1.,  254.,  252.,  255.,  255.,  255.]], dtype=float16)

In [17]: np.hypot(a, b, dtype=np.float64)
Out[17]: 
array([[   1.        ,  254.        ,  252.00198412,  255.        ,
         255.        ,  255.00196078]])

You might wonder why the dtype argument that I used in numpy.square and numpy.hypot is not shown in the functions' docstrings. Both of these functions are numpy "ufuncs", and the authors of numpy decided that it was better to show only the main arguments in the docstring. The optional arguments are documented in the reference manual.

Sign up to request clarification or add additional context in comments.

1 Comment

This worked! Thank you for the detailed explanation! Would using numpy.hypot be considered more "pythonic" than the way I am currently doing it?
0

For this simple case, it works perfectly fine:

In [1]: a = np.array([[ 0, 2, 4, 6, 8]])
In [2]: b = np.array([[ 1, 3, 5, 7, 9]])
In [3]: c = np.sqrt(np.square(a) + np.square(b))

In [4]: print(c)
[[  1.     3.60555128   6.40312424   9.21954446  12.04159458]]

You must be doing something wrong.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.