4

I have a numpy.float32 matrix V, then I did a division with a integer scalar value:

V = V/num

where num is an integer. The outcome is somewhat surprising that V is converted to a numpy.float64 matrix.

Can anyone help understand why this is so?

Thanks!

YC0
  • 61
  • 4
  • What, *exactly* is `num`? – juanpa.arrivillaga Nov 14 '17 at 21:06
  • 1
    It's probably because casting int to float32 is considered unsafe by numpy (try 'np.can_cast(int, np.float32`) – Paul Panzer Nov 14 '17 at 21:07
  • 1
    If I use an `int`, I still get an array of `np.float32`. Can you please provide a [mcve]? – juanpa.arrivillaga Nov 14 '17 at 21:08
  • 1
    @PaulPanzer it depends on the `int` in question, e.g. `np.can_cast(2**15, np.float32)` returns `True` for me, but `np.can_cast(2**16, np.float32)` returns `False` – juanpa.arrivillaga Nov 14 '17 at 21:09
  • @Paul Panzer np.can_cast(int, np.float32) does give a False. My understanding is that python uses int32 be default, then why converting int32 to numpy.float32 is a problematic operation? numpy.float32 has a range large enough to handle a conversion from int32. – YC0 Nov 14 '17 at 21:12
  • 1
    See https://stackoverflow.com/questions/45949263/numpy-casting-float32-to-float64 – user2357112 Nov 14 '17 at 21:12
  • @juanpa.arrivillaga, YC0, user2357112 Good points thanks for clarifying that. – Paul Panzer Nov 14 '17 at 21:14
  • @juanpa.arrivillaga `Vtest = np.zeros([1,1]).astype('float32')` `Vest_new = Vtest/65536` `type(Vest_new[0,0]))` – YC0 Nov 14 '17 at 21:16
  • If `num` is smaller or equal to 65535 (int16), the float32 won't be changed. The problem seems come from an int32. – YC0 Nov 14 '17 at 21:23
  • Just a heads up that the linked Q/A has this very informative [link](https://docs.scipy.org/doc/numpy/reference/generated/numpy.result_type.html) – Paul Panzer Nov 14 '17 at 21:34
  • Worth noting that numpy uses `int` to refer to the C `long`, which is sometimes `int32` and sometimes `int64`, depending on your platform - this is why @juanpa.arrivillaga cannot reproduce this, most likely – Eric Nov 14 '17 at 21:47
  • @YC0 "python" doesn't have sized-integers. Python `int` objects are arbitrarily large. Which is why python is happy to evaluate `2**128` – juanpa.arrivillaga Nov 14 '17 at 21:50
  • @ user2357112, Eric, juanpa.arrivillaga, Paul Panzer, thanks a lot! I think I have a much better idea now. It's sort of reasonable since numpy determines that float32 can not hold all the values of int32 losslessly. So that's why when I increased 65535 to 65536 will change the resullting type as a float64. – YC0 Nov 14 '17 at 22:17

1 Answers1

2

According to Numpy.result_type, numpy.float32 can not hold int32 losslessly. When the operation is with an int32, numpy will promotes the resulting value as a float64. Also according to @Eric, the actual int type may change in different environment, so a pre-test is a good practice to avoid some potential surprise.

A previous similar question is suggested for further reading:Numpy casting float32 to float64 . Numpy has a different treatment for purely scalar operations and the operations involving an array. In this case, the division operation involves a ndarray, so when num is smaller than 65536 but larger thant 255, numpy converts it as int16. Numpy determines int16 can be cast to float32 losslessly while int32 can't. This is shown by np.can_cast(np.int16, np.float32) gives True but np.can_cast(np.int32, np.float32) gives False.

Thanks for the insightful comments under the question. This answer is a short summary of these comments.

YC0
  • 61
  • 4