23

I'm using python 2.7.3, when I execute the following piece of code:

import numpy as np

a = np.array([[1,2,3],[4,5,6]])
a = a / float(2**16 - 1)
print a

This will result in he following output:

>> array([[1.52590219e-05, 3.05180438e-05, 4.57770657e-05],
>>       [6.10360876e-05, 7.62951095e-05, 9.15541314e-05]])

Exactly as expected, however when I execute the following piece of code:

import numpy as np

a = np.array([[1,2,3],[4,5,6]])
a /= float(2**16 - 1)
print a

I get the following output:

>> array([[0, 0, 0],
>>        [0, 0, 0]])

I expected the same output as in the previous example, I don't understand the different ouput, which seems to be a result of using a /= float(2**16 - 1) vs a = a / float(2**16 - 1).

Gio
  • 3,242
  • 1
  • 25
  • 53
  • 1
    [I'm reopening this. It's related to the original proposed duplicate, but none of the answers to that question address the dtype issue involved. There's probably another duplicate somewhere, but it's not that one.] – DSM Aug 13 '15 at 12:10
  • @DSM Agreed, the linked question was really not explaining what’s going on here. It explains why there *can* be a different result, but not *why* it happens in this case. – poke Aug 13 '15 at 12:12
  • Related question: [Unexpected behavior for numpy self division](http://stackoverflow.com/q/15907484/832621) – Saullo G. P. Castro Aug 13 '15 at 12:13

1 Answers1

36

From the documentation:

Warning:

In place operations will perform the calculation using the precision decided by the data type of the two operands, but will silently downcast the result (if necessary) so it can fit back into the array. Therefore, for mixed precision calculations, A {op}= B can be different than A = A {op} B. For example, suppose a = ones((3,3)). Then, a += 3j is different than a = a + 3j: while they both perform the same computation, a += 3 casts the result to fit back in a, whereas a = a + 3j re-binds the name a to the result.

Since your array was an array of integers, when using the in-place operations, the result will be downcasted to integers again.

If you change your array so it stores floats originally, then the results (which are floats) can be stored in the original array, and your code will work fine:

>>> a = np.array([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]])
>>> a /= float(2**16 - 1)
>>> a
array([[  1.52590219e-05,   3.05180438e-05,   4.57770657e-05],
       [  6.10360876e-05,   7.62951095e-05,   9.15541314e-05]])
poke
  • 369,085
  • 72
  • 557
  • 602
  • I would not say that it was down-cast to integers, I would say it was preserved as integers and not up-cast to float. – tacaswell May 08 '23 at 18:08
  • 1
    @tacaswell It literally says “downcast” in the documentation that I quoted in my answer. – poke May 13 '23 at 11:31