Специализация битового поля в python

Вот код на С++:

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

Мой вопрос в том, как я могу получить этот результат, используя битовые массивы или любой другой метод, который дает правильный ответ.


person Muhammad Ali Qadri    schedule 05.08.2016    source источник


Ответы (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
person Mark Tolonen    schedule 06.08.2016
comment
спасибо за ответ, я отмечу его как правильный. Также просто из любопытства, как бы я сделал то же самое, используя битовые массивы? - person Muhammad Ali Qadri; 06.08.2016

Я думаю, что это может сделать то, что вы хотите (пока x неотрицательно и может быть записано с использованием битов b).

def sign_extend(x, b):
    if x >= 2 ** (b - 1):
        return x - 2 ** b
    else:
        return x
person Nikola Benes    schedule 05.08.2016
comment
ваш ответ правильный, но я надеялся получить решение, используя битовый массив или код структуры. Поскольку было бы разумнее использовать битовые поля, как указано в приведенном коде С++ - person Muhammad Ali Qadri; 05.08.2016
comment
Обратите внимание, что 1 << n намного быстрее, чем 2 ** n. - person PM 2Ring; 06.08.2016