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

Два бинарных дополнения в Python?

Целые числа в Python хранятся в двух дополнениях, правильно?

Хотя:

>>> x = 5
>>> bin(x)
0b101

и

>>> x = -5
>>> bin(x)
-0b101

Это довольно хромает. Как мне получить python, чтобы дать мне числа в бинарных битах REAL и без него? Итак:

>>> x = 5
>>> bin(x)
0101
>>> y = -5
>>> bin(y)
1011
4b9b3361

Ответ 1

Не уверен, как получить то, что вы хотите, используя стандартную библиотеку lib. Есть несколько скриптов и пакетов, которые будут делать конверсию для вас.

Я просто хотел отметить "почему", и почему он не хромой.

bin() не возвращает двоичные биты. он преобразует число в двоичную строку. ведущий "0b" сообщает интерпретатору, что вы имеете дело с двоичным числом, в соответствии с определением языка python. таким образом, вы можете напрямую работать с двоичными числами, например

>>> 0b01
1
>>> 0b10
2
>>> 0b11
3
>>> 0b01 + 0b10
3

что не хромой. это здорово.


http://docs.python.org/library/functions.html#bin

бен (х)

Преобразование целочисленного числа в двоичную строку.

http://docs.python.org/reference/lexical_analysis.html#integers

Целочисленные и длинные целочисленные литералы описываются следующими лексическими определениями:

bininteger:: = "0" ( "b" | "B" ) bindigit +

     

bindigit:: = "0" | "1"

Ответ 2

Он лучше всего работает, если вы создаете маску. Таким образом вы указываете, как далеко подписать расширение.

>>> bin(-27 & 0b1111111111111111)
'0b1111111111100101'

Или, возможно, в целом:

def bindigits(n, bits):
    s = bin(n & int("1"*bits, 2))[2:]
    return ("{0:0>%s}" % (bits)).format(s)

>>> print bindigits(-31337, 24)
111111111000010110010111

В базовой теории фактическая ширина числа зависит от размера хранилища. Если это 32-разрядное число, то отрицательное число имеет 1 в MSB набора из 32. Если это 64-битное значение, то для отображения будет 64 бита.

Но в Python целая точность ограничивается только ограничениями вашего оборудования. На моем компьютере это действительно работает, но он потребляет 9 ГБ оперативной памяти только для хранения значения x. Все выше, и я получаю MemoryError. Если бы у меня было больше ОЗУ, я мог бы хранить большие числа.

>>> x = 1 << (1 << 36)

Итак, имея в виду, какое двоичное число представляет -1? Как показывает предыдущий пример, Python способен интерпретировать буквально миллионы (и даже миллиарды) бит точности. В 2 дополнениях бит знака продолжается до упора влево, но в Python нет заранее определенного количества бит; есть столько, сколько вам нужно.

Но тогда вы сталкиваетесь с двусмысленностью: делает ли двоичный 1 1 или -1? Ну, это может быть так. Представляет 111 7 или -1? Опять же, это может быть и то. Таким образом, 111111111 представляет 511, или -1... ну, и то и другое, в зависимости от вашей точности.

Python нуждается в способе представления этих чисел в двоичном формате, чтобы не было двусмысленности их значения. Префикс 0b просто говорит, что "это число в двоичном формате". Точно так же, как 0x означает "это число в шестнадцатеричном формате". Поэтому, если я скажу 0b1111, как узнать, хочет ли пользователь -1 или 15? Существует два варианта:

Вариант A: Знаковый бит
Вы можете объявить, что все числа подписаны, а самый левый бит - знаковый бит. Это означает, что 0b1 равно -1, а 0b01 равно 1. Это также означает, что 0b111 также равно -1, а 0b0111 равно 7. В конце концов, это, вероятно, более запутанно, чем полезно, особенно потому, что В большинстве случаев бинарная арифметика будет беззнакомой,, и люди с большей вероятностью будут ошибаться, случайно отметив число как отрицательное, потому что они не содержат явного знакового бита.

Вариант B: Индикация знака
С помощью этой опции двоичные числа представлены без знака, а отрицательные числа имеют префикс "-", как и в десятичном. Это (а) более согласовано с десятичной, (б) более совместимо с тем, как бинарные значения, скорее всего, будут использоваться. Вы теряете возможность указывать отрицательное число, используя его два представления представления, но помните, что два дополнения - это деталь реализации хранилища, а не правильное указание самого базового значения. Это не должно быть то, что пользователь должен понять.

В конце концов, вариант B имеет наибольший смысл. Там меньше путаницы, и пользователю не требуется понимать детали хранения.

Ответ 3

Чтобы правильно интерпретировать двоичную последовательность как два дополнения, необходимо иметь длину, связанную с последовательностью. Когда вы работаете с низкоуровневыми типами, которые напрямую соответствуют регистрам CPU, существует неявная длина. Поскольку целые числа Python могут иметь произвольную длину, на самом деле не существует внутреннего формата двух дополнений. Поскольку число, не связанное с числом, не существует, невозможно отличить положительное и отрицательное числа. Чтобы удалить двусмысленность, bin() содержит знак минуса при форматировании отрицательного числа.

Тип произвольной длины Python на самом деле использует внутренний формат знаковой величины. Логические операции (смещение бит и т.д.) Предназначены для имитации двух дополнительных форматов. Это типично для библиотек с высокой точностью.

Ответ 4

Я не совсем уверен, что вы в конечном итоге хотите сделать, но вы можете посмотреть на bitarray.

Ответ 5

tobin = lambda x, count=8: "".join(map(lambda y:str((x>>y)&1), range(count-1, -1, -1)))

например.

tobin(5)      # =>  '00000101'
tobin(5, 4)   # =>      '0101'
tobin(-5, 4)  # =>      '1011'

Или как четкие функции:

# Returns bit y of x (10 base).  i.e. 
# bit 2 of 5 is 1
# bit 1 of 5 is 0
# bit 0 of 5 is 1
def getBit(y, x):
    return str((x>>y)&1)

# Returns the first `count` bits of base 10 integer `x`
def tobin(x, count=8):
    shift = range(count-1, -1, -1)
    bits = map(lambda y: getBit(y, x), shift)
    return "".join(bits)

(Адаптировано из комментарий W.J. Van de Laan)

Ответ 6

Для положительных чисел просто используйте:

bin(x)[2:].zfill(4)

Для отрицательных чисел это немного отличается:

bin((eval("0b"+str(int(bin(x)[3:].zfill(4).replace("0","2").replace("1","0").replace("2","1"))))+eval("0b1")))[2:].zfill(4)

В целом script, вот как это должно выглядеть:

def binary(number):
    if number < 0:
        return bin((eval("0b"+str(int(bin(number)[3:].zfill(4).replace("0","2").replace("1","0").replace("2","1"))))+eval("0b1")))[2:].zfill(4)
    return bin(number)[2:].zfill(4)      
x=input()
print binary(x)

Ответ 7

def tobin(data, width):
    data_str = bin(data & (2**width-1))[2:].zfill(width)
    return data_str

Ответ 8

Используйте срезы, чтобы избавиться от нежелательных "0b".

  

bin(5)[2:]    '101'

  

или если вы хотите цифры,

  

tuple ( bin(5)[2:] )    ('1', '0', '1')

  

или даже

  

map( int, tuple( bin(5)[2:] ) )    [1, 0, 1]

  

Ответ 9

Модификация на tylerl очень полезный ответ, который обеспечивает расширение знака для положительных чисел, а также отрицательный (без проверки ошибок).

def to2sCompStr(num, bitWidth):
    num &= (2 << bitWidth-1)-1 # mask
    formatStr = '{:0'+str(bitWidth)+'b}'
    ret =  formatStr.format(int(num))
    return ret

Пример:

In [11]: to2sCompStr(-24, 18)
Out[11]: '111111111111101000'

In [12]: to2sCompStr(24, 18)
Out[12]: '000000000000011000'

Ответ 10

Надеюсь, это решит вашу проблему

num = input("Enter number : ")
bin_num=bin(num)
binary = '0' + binary_num[2:]
print binary

Ответ 11

Вот немного более читаемая версия Tylerl answer, например, скажем, вы хотите -2 в своем 8 -bits отрицательное представление "двух дополнений":

bin(-2 & (2**8-1))

2 ** 8 обозначает девятый бит (256), вычитает 1, и все предыдущие биты установлены на один (255)

для 8 и 16 бит масок, вы можете заменить (2 ** 8-1) на 0xff или 0xffff. Шестнадцатеричная версия становится менее прочитанной после этой точки.

Если это неясно, здесь есть регулярная функция:

def twosComplement (value, bitLength) :
    return bin(value & (2**bitLength - 1))