Подтвердить что ты не робот

Как конвертировать подписанное целое без знака в python

Скажем, у меня есть это число i = -6884376. Как я могу ссылаться на него как на неподписанную переменную? Что-то вроде (unsigned long)i в C.

4b9b3361

Ответ 1

Предполагая, что

  • У вас есть представления с 2-мя дополнениями; и,
  • Под (unsigned long) вы подразумеваете 32-разрядное целое число без знака,

вам просто нужно добавить 2**32 (or 1 << 32) к отрицательному значению.

Например, примените это к -1:

>>> -1
-1
>>> _ + 2**32
4294967295L
>>> bin(_)
'0b11111111111111111111111111111111'

Предположение № 1 означает, что вы хотите, чтобы -1 рассматривалась как сплошная строка из 1 бита, а предположение №2 означает, что вы хотите 32 из них.

Никто, кроме вас, не может сказать, каковы ваши скрытые предположения. Если, например, у вас есть представления с 1'-дополнением, тогда вам нужно вместо этого применить префикс ~. Целые числа Python усердно работают, чтобы создать иллюзию использования бесконечно широкого представления с двумя дополнениями (например, регулярное 2 дополнение, но с бесконечным числом "знаковых битов" ).

И чтобы дублировать то, что делает компилятор платформы C, вы можете использовать модуль ctypes:

>>> import ctypes
>>> ctypes.c_ulong(-1)  # stuff Python -1 into a C unsigned long
c_ulong(4294967295L)
>>> _.value
4294967295L

C unsigned long имеет значение 4 байта в поле, которое запускало этот образец.

Ответ 2

Чтобы получить значение, эквивалентное вашему C-броску, просто поразрядно и с соответствующей маской. например если unsigned long 32-битный:

>>> i = -6884376
>>> i & 0xffffffff
4288082920

или 64-битная версия:

>>> i & 0xffffffffffffffff
18446744073702667240

Имейте в виду, что хотя это дает вам значение, которое вы имели бы в C, оно все равно является значением со знаком, поэтому любые последующие вычисления могут дать отрицательный результат, и вам придется продолжать применять маску для имитации 32 или 64 битное вычисление.

Это работает, потому что, хотя Python выглядит так, как будто он хранит все числа в виде знака и величины, побитовые операции определяются как работа с двумя значениями дополнения. C хранит целые числа в двух дополнениях, но с фиксированным числом битов. Битовые операторы Python действуют на значения, дополняющие два, но как будто они имеют бесконечное число битов: для положительных чисел они расширяются влево до бесконечности с нулями, но отрицательные числа расширяются влево с единицами. Оператор & изменит эту левую строку единиц на нули и оставит вам только те биты, которые вписались бы в значение C.

Отображение значений в шестнадцатеричном формате может сделать это более понятным (и я переписал строку f в качестве выражения, чтобы показать, что мы заинтересованы в 32 или 64 битах):

>>> hex(i)
'-0x690c18'
>>> hex (i & ((1 << 32) - 1))
'0xff96f3e8'
>>> hex (i & ((1 << 64) - 1)
'0xffffffffff96f3e8L'

Для 32-битного значения в C положительные числа доходят до 2147483647 (0x7fffffff), а для отрицательных чисел устанавливается верхний бит, начиная от -1 (0xffffffff) и заканчивая -2147483648 (0x80000000). Для значений, которые полностью помещаются в маску, мы можем полностью изменить процесс в Python, используя меньшую маску для удаления знакового бита, а затем вычитая знаковый бит:

>>> u = i & ((1 << 32) - 1)
>>> (u & ((1 << 31) - 1)) - (u & (1 << 31))
-6884376

Или для 64-битной версии:

>>> u = 18446744073702667240
>>> (u & ((1 << 63) - 1)) - (u & (1 << 63))
-6884376

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

Ответ 3

Python не имеет встроенных неподписанных типов. Вы можете использовать математические операции для вычисления нового int, представляющего значение, которое вы получите на C, но нет никакого значения unsigned value для Python int. Python int представляет собой абстракцию целочисленного значения, а не прямой доступ к целому числу фиксированного байта.

Ответ 4

Вы можете использовать встроенную библиотеку struct Python:

Код:

import struct

i = -6884376
print('{0:b}'.format(i))

packed = struct.pack('>l', i)  # Packing a long number.
unpacked = struct.unpack('>L', packed)[0]  # Unpacking a packed long number to unsigned long
print(unpacked)
print('{0:b}'.format(unpacked))

Out:

-11010010000110000011000
4288082920
11111111100101101111001111101000

Decode:

dec_pack = struct.pack('>L', unpacked)  # Packing an unsigned long number.
dec_unpack = struct.unpack('>l', dec_pack)[0]  # Unpacking a packed unsigned long number to long (revert action).
print(dec_unpack)

Out:

-6884376

[Примечание]:

  • > - операция BigEndian.
  • l длинный.
  • L без знака долго.
  • В архитектуре amd64 int и long являются 32-битными, поэтому вы можете использовать i и I вместо l и L соответственно.

Ответ 5

просто используйте abs для преобразования неподписанного в подписанный в Python

 a=-12
b=abs(a)
print(b)

Выход:  12

Ответ 6

В Python нет встроенных функций для преобразования int в unsigned int. Вместо этого он имеет более длинный диапазон.

>>> val = 9223372036854775807 (maximum value of int 64)
>>> type(val)
<type 'int'>
>>> val += 1
>>> type(val)
<type 'long'>

Увеличивая значение val на 1, я превышаю предел 64-разрядного целого числа со знаком, и значение преобразуется в long. Если бы Python использовал или преобразовал в целое число без знака, val все равно был бы int. Или не долго.

Целые числа со знаком представляются битом, обычно наиболее значимым битом, который устанавливается равным 0 для положительных чисел или 1 для отрицательных чисел. Что Val & 0xff делает это на самом деле val & 0x000000ff (на 32-битной машине). Другими словами, бит со знаком установлен в 0, а значение без знака эмулируется.

Пример:

>>> val = -1
>>> val & 0xff
255