2016-06-30 4 views
4

私は、符号なし整数を型キャストするときに、python/numpyのやり方でやや混乱します。uint8にintを追加すると、不思議なtypecastingですか?

例:

In[0]: y 
Out[0]: array([0], dtype=uint8) 

IはUINT8がゼロに戻る255回のそれサイクルよりも大きい値を有する整数を格納することができないことを理解する:

import numpy as np 
x = np.array([255], dtype=np.uint8) 
y = x + 1 

これは結果を与えます。私はこれを期待しています。

今、私は試してみてください。

In[1]: z 
Out[1]: array([511], dtype=uint16) 

をので、この場合には型がより多くを保持するために多くのバイトを1に変更されていますが、整数であることのみとき:与え

z = x + 256 

追加されたものはそれ自体がより小さな型には適合しません。 (興味深いことにx + 255はuint16の結果を与えません)

これは私をいくらか奇妙な振る舞いにします。それの背後にある論理はありますか?私はもっ​​と一貫していることは、最初の例の場合でもuint16への型の変更を行うことだと思っていたでしょう。

+0

256はuint8として表現できません。 – adrianN

+0

また、255 + 1もないので、なぜこれが起こりますか? – JesseC

+1

numpyは結果のサイズではなく、オペランドのサイズを調べているようです。興味深い質問です。 –

答えて

3

この動作は、アレイのキャスティングを絶対最小限に抑えるという理解できる欲求に由来するようです。

リテラル1intを入力した

z = np.uint8(255) 
z + 1 
# 256 
type(z+1) 
# numpy.int64 

を考えてみましょう。この場合、両方のオペランドがnp.int64にキャストされているようです。しかし、これは結果とは関係ありません!

zz = np.uint8(1) 
type(zz + 1) 
# numpy.int64 

ただし、単純な整数の代わりに配列を使用すると、キャストは異なります。それは確かに100%はこれが必要になります知っている場合

x = np.array([255], dtype=np.uint8) 
x + 1 
# array([0], dtype=uint8) 

は、別の種類の配列全体をキャストするために大規模な計算作業になると、これはおそらくそうであるように思えるので、これはのみ行われますの前に、すべての配列要素を調べます。つまり、他のオペランド自体が現在の型に収まらない場合に限ります。実際には、我々は

b = np.int16(1) 
x+b 
# array([0], dtype=uint8) 

を取る場合でも、それは実際にはすべての配列の型を保存するために、より小さな型に右側のオペランドをキャストします。一方、2つのnp.arraysを追加する場合、型変換は常により大きな型に行われます。

かいつまん: - 簡単な整数の加算は、常にオペランド の大きな型にキャスト - これは整数を表現するのに十分であればnumpyの配列の追加と整数は配列の型にキャストし、他に整数のタイプ - 2つのnumpy配列の加算は、より大きな型のオペランドに(2つの整数の場合と同様に)キャストします。