Специализация битового поля в питоне
Вот код на C++:
void sign_extending(int x)
{
int r; // resulting sign extended number goes here
struct {signed int x:5 ;} s;
r = s.x = x;
cout << r;
}
void Run()
{
int x=29; // this 29 is -3 ( 11101 ) in 5 bits
// convert this from using 5 bits to a full int
sign_extending(x);
}
Выход этого кода -3. Когда я пытаюсь воспроизвести этот код на python, генерируется битовое поле 11101, но когда ответ преобразуется в int, дается ответ 29.
Ниже приведен код Python:
from bitarray import *
def sign_extending(x) :
s = bitarray(5)
r = s = bin(x) #resulting sign extended number goes in r
print (int(r, 2))
x = 29 #this 29 is -3 ( 11101 ) in 5 bits. Convert this from using 5 bits to a full int
sign_extending(x)
Я также использовал структуры ctypes в качестве альтернативного кода, но бесполезно:
from ctypes import *
def sign_extending(x, b):
class s(Structure):
_fields_ = [("x", c_int, 5)]
r = s.x = x
return r #resulting sign extended number goes in r
x = 29; #this 29 is -3 ( 11101 ) in 5 bits.
r = sign_extending(x, 5) #Convert this from using 5 bits to a full int
print r
Мой вопрос заключается в том, как мне получить этот результат, используя битовые массивы или любой другой метод, который дает правильный ответ.
2 ответа
В вашем коде s
это класс и класс x
элемент на самом деле представляет тип поля, поэтому назначение s.x = 29
по сути, уничтожает этот объект и присваивает ему обычный Python int. Пример:
>>> from ctypes import *
>>> class S(Structure):
... _fields_ = [('x',c_int,5)]
...
>>> S.x
<Field type=c_long, ofs=0:0, bits=5>
>>> S.x = 29
>>> S.x
29
Кроме того, даже если вы сначала создадите экземпляр, r = s.x = 29
не делает s.x = 29
затем r = s.x
как в C/C++, но по существу r=29
а также s.x=29
, Пример:
>>> from ctypes import *
>>> class S(Structure):
... _fields_ = [('x',c_int,5)]
...
>>> s=S()
>>> r=s.x=29
>>> s.x
-3
>>> r
29
Таким образом, чтобы исправить, создать экземпляр класса, назначить s.x = 29
и вернуть его:
from ctypes import *
def sign_extending(x, b):
class S(Structure):
_fields_ = [("x", c_int, b)]
s=S()
s.x = x
return s.x
x = 29; #this 29 is -3 ( 11101 ) in 5 bits.
r = sign_extending(x, 5) #Convert this from using 5 bits to a full int
print r
Выход:
-3
Я думаю, что это может делать то, что вы хотите (если х неотрицателен и может быть записан с использованием битов b).
def sign_extend(x, b):
if x >= 2 ** (b - 1):
return x - 2 ** b
else:
return x