[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