2017-02-02 7 views
1

私は、次のnp.uint8配列を考えてみましょう:私はnp.uint16への変換を行うときにPythonでCスタイルのTypecastingを実行するにはどうしたらいいですか?

In [9]: a = np.array([0x34, 0xF3, 0x87, 0x42]).astype(np.uint8) 
In [10]: a 
Out[10]: array([0x34, 0xf3, 0x87, 0x42], dtype=uint8) 

は今、私は次を得る:

In [11]: b = a.astype(np.uint16) 
In [12]: b 
Out[12]: array([0x34, 0xf3, 0x87, 0x42], dtype=uint16) 

これが起こることが予想されているものですが、I別のものが欲しい。これは私を与えるだろう

unsigned char a[] = {0x34, 0xF3, 0x87, 0x42}; 
unsigned short* b = (unsigned short*)a; 

:それはuint16unsigned short)の要素を含む配列であるかのようにあなたがタイプuint8unsigned char)と同じ配列を持っているし、あなたがそれにアクセスするCに、例えば 、 、Cのために期待通りに:

0x34 0xF3 0x87 0x42 // for a 
0xF334 0x4287  // for b, little or big endian, for me doesn't matter 

私の質問は、どうすればPythonでこのようなことができますか? (新しい配列を作成せずに、別の型に1種類から変換することも可能ですか?)

私は少し一緒にそうようにシフトすると2つのバイトを追加することによって、新しい配列を作成することができます。

#! /usr/bin/python3 

import numpy as np 

np.set_printoptions(formatter={'int':hex}) 

# I assume, a has the len 2*n and b has the len n (for conversion from 2*n Bytes in n 2Bytes) 
a = np.array([0x31, 0x41, 0x59, 0x26, 0x53, 0x58, 0x97, 0x93]).astype(np.uint8) 
b = np.array([(a[2*i]<<8)+a[2*i+1] for i in range(0, len(a) // 2)]).astype(np.uint16) 

print("a: {}".format(a)) # a: [0x31 0x41 0x59 0x26 0x53 0x58 0x97 0x93] 
print("b: {}".format(b)) # b: [0x3141 0x5926 0x5358 0x9793] 

私はこれを必要とします非常に大きな配列(多かれ少なかれ)のために、私はこれがPythonでより効率的にできるかどうかを尋ねています。

答えて

2

私は実際に(@user2357112 already explained why)それを行うことをお勧めしませんが、あなたはまた、手動で(設定を変更することができます)dtype属性:

>>> import numpy as np 
>>> a = np.array([0x34, 0xF3, 0x87, 0x42]).astype(np.uint8) 
>>> a.dtype = np.uint16 
>>> a 
array([62260, 17031], dtype=uint16) 
3
b = a.view(np.uint16) 

これは危険でエラーが発生しやすい操作です。エンディアンなど、C++で覚えておかなければならないすべての注意点を覚えておいてください。連続していない配列のメモリレイアウトなどの追加の注意点についても心配する必要があります。少なくとも厳密なエイリアシングは誰かの問題です。実装はCの厳密なエイリアシング規則に違反している可能性がありますが、コンパイラフラグなどを設定して動作を定義していることを願っています。 (uint8はとても厳しいエイリアシングが適用されない、unsigned charですが、ndarray.viewuint64のようなものを可能にする - 。>float64再解釈)

+1

ですから、基本的には私にはおすすめできません。 b = a.view(np.uint16)?私の問題では、uintXからuintYへのキャストのみを行います。また、リトルエンディアン変換は問題ではありません。私は(具体的に)S-Boxを持っているので、それが必要です。また、定義された動作を得るためにPythonでフラグを設定できますか? (例えばnumpyを大きくするか小さいエンディアンにするなど) – PiMathCLanguage

+2

@PiMathCLanguage:[dtypeのエンディアンを指定できます](https://docs.scipy.org/doc/numpy/reference/arrays.dtypes.html) )。例えば、 'np.array(...、dtype = ' i2'がビッグエンディアンであるのに対して、dtypeのリトルエンディアンの2バイト整数を使用します。 – user2357112