[Numpy-discussion] Casting and promotion rules (e.g. int + uint64 => float)
Chris Barker - NOAA Federal
chris.barker at noaa.gov
Mon Mar 11 13:07:05 EDT 2013
On Fri, Mar 8, 2013 at 8:23 AM, Sergio Callegari
<sergio.callegari at gmail.com> wrote:
> I have noticed that numpy introduces some unexpected type casts, that are
> in some cases problematic.
There has been a lot of discussion about casting on this list in the
last couple months -- I suggest you peruse that discussion and see
what conclusions it has lead to.
> A very weird cast is
>
> int + uint64 -> float
I think the idea here is that an int can hold negative numbers, so you
can't put it in a uint64 -- but you can't put a uint64 into a signed
int64. A float64 can hold the range of numbers of both a int and
uint64, so it is used, even though it can't hold the full precision
of a uint64 (far from it!)
> Another issue is that variables unexpectedly change type with accumulation
> operators
>
> a=np.uint64(1)
> a+=1
>
> now a is float
yeah -- that should NEVER happen -- += is supposed to be an iin=place
operator, it should never change the array! However, what you've
crated here is not an array, but a numpy scalar, and the rules are
different there (but should they be?). I suspect that part of the
issue is that array scalars behave a bit more like the built-in numpy
number types, and thus += is not an in-place operator, but rather,
translates to:
a = a + 1
and as you've seen, that casts to a float64. A little test:
In [34]: d = np.int64(2)
In [35]: e = d
# e and d are the same object
In [36]: d += 1
In [37]: e is d
Out[37]: False
# they are not longer the same object -- the += created a new object
In [38]: type(d)
Out[38]: numpy.int64
# even though it's still the same type (no casting needed)
If you do use an array, you don't get casting with +=:
In [39]: a = np.array((1,), dtype=np.uint64)
In [40]: a
Out[40]: array([1], dtype=uint64)
In [41]: a + 1.0
Out[41]: array([ 2.])
# got a cast with the additon and creation of a new array
In [42]: a += 1.0
In [43]: a
Out[43]: array([2], dtype=uint64)
# but no cast with the in-place operator.
Personally, I think the "in-place" operators should be just that --
and only work for mutable objects, but I guess the ability to easily
increment in integer was just too tempting!
-Chris
--
Christopher Barker, Ph.D.
Oceanographer
Emergency Response Division
NOAA/NOS/OR&R (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax
Seattle, WA 98115 (206) 526-6317 main reception
Chris.Barker at noaa.gov
More information about the NumPy-Discussion
mailing list