Python中的整数存储在两个补码中,对吗?
虽然:
>>> x = 5
>>> bin(x)
0b101
和
>>> x = -5
>>> bin(x)
-0b101
那太蹩脚了。我怎么让python给我真正的二进制位数,而没有它的前面的0b?所以:
>>> x = 5
>>> bin(x)
0101
>>> y = -5
>>> bin(y)
1011
答案 0 :(得分:62)
如果您提供面具,效果最佳。这样就可以指定签名扩展的范围。
>>> 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位数字,那么负数在一组32的MSB中有1。如果它是64位值,那么有64位要显示。
但在Python中,整数精度仅限于硬件的约束。在我的计算机上,这个实际上正常工作,但它只消耗9GB的RAM来存储 x 的值。任何更高的东西,我得到一个MemoryError。如果我有更多的RAM,我可以存储更大的数字。
>>> 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: 符号指示
使用此选项,二进制数字表示无符号,负数字表示“ - ”前缀,就像它们在十进制中一样。这是(a)与十进制更一致,(b)与最有可能使用二进制值的方式更兼容。您无法使用其二进制补码表示来指定负数,但请记住,两个补码是存储实现详细信息,而不是对基础值本身的正确指示。它不应该是用户必须理解的东西。
最后,选项B最有意义。混淆较少,用户无需了解存储详细信息。
答案 1 :(得分:13)
要将二进制序列正确解释为二进制补码,需要与序列关联的长度。在处理与CPU寄存器直接对应的低级类型时,存在隐式长度。由于Python整数可以具有任意长度,因此实际上没有内部二进制补码格式。由于没有与数字相关的长度,因此无法区分正数和负数。为了消除歧义,bin()在格式化负数时包含减号。
Python的任意长度整数类型实际上使用符号幅度内部格式。逻辑运算(位移,和/或等)旨在模仿二进制补码格式。这是多个精度库的典型特征。
答案 2 :(得分:3)
不确定如何使用标准库获取所需内容。有一些脚本和包可以为你进行转换。
我只想注意“为什么”,以及为什么它不蹩脚。
bin()不返回二进制位。它将数字转换为二进制字符串。根据python语言定义,前导'0b'告诉解释器你正在处理二进制数。这样你就可以直接使用二进制数,比如这个
>>> 0b01
1
>>> 0b10
2
>>> 0b11
3
>>> 0b01 + 0b10
3
那不是蹩脚的。那很好。
http://docs.python.org/library/functions.html#bin
箱(x)的
将整数转换为二进制字符串。
http://docs.python.org/reference/lexical_analysis.html#integers
整数和长整数文字由以下词汇定义描述:
bininteger :: =“0”(“b”|“B”)bindigit +
bindigit :: =“0”| “1”
答案 3 :(得分:3)
tobin = lambda x, count=8: "".join(map(lambda y:str((x>>y)&1), range(count-1, -1, -1)))
e.g。
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's评论)
答案 4 :(得分:2)
我不完全确定您最终想要做什么,但您可能希望查看bitarray包。
答案 5 :(得分:1)
对于正数,只需使用:
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)
作为一个完整的脚本,它应该是这样的:
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)
答案 6 :(得分:1)
def tobin(data, width):
data_str = bin(data & (2**width-1))[2:].zfill(width)
return data_str
答案 7 :(得分:1)
使用切片去掉不需要的'0b'。
bin(5)[2:]
'101'
或者如果你想要数字,
tuple ( bin(5)[2:] )
('1','0','1')
甚至
map( int, tuple( bin(5)[2:] ) )
[1,0,1]
答案 8 :(得分:1)
修改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'
答案 9 :(得分:1)
没必要,已经是。只是python选择以不同的方式表示它。如果你开始分别打印每个半字节,它将显示其真实的颜色。
IDialogWaterfallStep
输出很简单:
checkNIB = '{0:04b}'.format
checkBYT = lambda x: '-'.join( map( checkNIB, [ (x>>4)&0xf, x&0xf] ) )
checkBTS = lambda x: '-'.join( [ checkBYT( ( x>>(shift*8) )&0xff ) for shift in reversed( range(4) ) if ( x>>(shift*8) )&0xff ] )
print( checkBTS(-0x0002) )
现在,当你想显示一个半字节的二进制补码时,它会恢复原始表示形式,但是如果将它分成半部分,那么它仍然是可能的。 请记住,最好的结果是使用负十六进制和二进制整数解释简单数字,而不是十六进制,您可以设置字节大小。
答案 10 :(得分:1)
一个减号的意思是 mod value减去正值。 因此,我认为,补充-27的简单方法是
bin((1<<32) - 27) // 32 bit length '0b11111111111111111111111111100101'
bin((1<<16) - 27)
bin((1<<8) - 27) // 8 bit length '0b11100101'
答案 11 :(得分:1)
您可以使用 Binary fractions 包。这个包用二进制整数和二进制分数实现 >>> from binary_fractions import TwosComplement
>>> TwosComplement.to_float("11111111111") # TwosComplement --> float
-1.0
>>> TwosComplement.to_float("11111111100") # TwosComplement --> float
-4.0
>>> TwosComplement(-1.5) # float --> TwosComplement
'10.1'
>>> TwosComplement(1.5) # float --> TwosComplement
'01.1'
>>> TwosComplement(5) # int --> TwosComplement
'0101'
。您可以将二进制分数字符串转换为二进制补码,反之亦然
示例:
Binary
要将它与二进制而不是浮点一起使用,您可以在同一个包中使用 # no. of rows to read per chunk
factor = 10**7
# gather files to combine
file_lst = []
for fl in os.listdir('output/'):
if not fl.startswith('combined'):
file_lst.append(fl)
# combined file name
with tb.File('output/combined.h5', 'w') as file_cmb:
for file_idx, filename in enumerate(file_lst):
if file_idx == 0:
# copy file-1 dataset to new file
with tb.File(f'output/{filename}', 'r') as file1:
z = file1.copy_node('/', name='dataset_1', newparent=file_cmb.root, newname='dataset_1')
print(f'File1-{filename} shape: {file1.root.dataset_1.shape[0]}')
else:
with tb.File(f'output/{filename}', 'r') as file2:
file2_dset = file2.root.dataset_1
shape = file2_dset.shape[0]
print(f'File2-{filename} shape: {shape}')
chunk_loops = shape//factor
if shape > chunk_loops*factor:
chunk_loops += 1
chunk_start, chunk_end = 0, 0
for alpha in range(chunk_loops):
if chunk_start + factor > shape:
chunk_end = shape
else:
chunk_end = chunk_start + factor
z.append(file2_dset[chunk_start:chunk_end])
chunk_start = chunk_end
print(f'Combined file shape: {z.shape}')
类。
PS:无耻的插件,我是这个包的作者。
答案 12 :(得分:0)
这是Tylerl answer的一个更具可读性的版本,例如,假设你想要 8位的负面表示 -2 补充“:
bin(-2 & (2**8-1))
2 ** 8代表第九位(256),减去1,你将所有前面的位设置为一(255)
对于8位和16位掩码,可以用0xff或0xffff替换(2 ** 8-1)。在该点之后,十六进制版本变得不那么readalbe。
如果不清楚,这是它的常规功能:
def twosComplement (value, bitLength) :
return bin(value & (2**bitLength - 1))
答案 13 :(得分:0)
我们可以利用按位异或的特性。使用按位 XOR 翻转位,然后加 1。然后您可以使用 python 内置的 bin() 函数来获取 2 的补码的二进制表示。这是一个示例函数:
def twos_complement(input_number):
print(bin(input_number)) # prints binary value of input
mask = 2**(1 + len(bin(input_number)[2:])) - 1 # Calculate mask to do bitwise XOR operation
twos_comp = (input_number ^ mask) + 1 # calculate 2's complement, for negative of input_number (-1 * input_number)
print(bin(twos_comp)) # print 2's complement representation of negative of input_number.
答案 14 :(得分:-1)
我希望这可以解决您的问题`
num = input("Enter number : ")
bin_num=bin(num)
binary = '0' + binary_num[2:]
print binary