问题描述
我正在尝试输出负数的二进制表示形式,每次的可用字节最少.
I am trying to output the binary representation of an negative number with the least bytes available each time.
示例:
-3 -> 101
-10 -> 10110
推荐答案
以下是使用Python 3整数的.bit_length
方法执行此操作的方法.它还使用字符串.format
方法将整数转换为二进制字符串.对于非负数,此函数返回以'0'开头的字符串,以便可以将它们与负数区分开.
Here's a way to do this using the .bit_length
method of Python 3 integers. It also uses the string .format
method to do the integer to binary string conversion. This function returns a string starting with '0' for non-negative numbers so that they can be distinguished from negative numbers.
def twos_complement(n):
m = n + 1 if n < 0 else n
bitlen = 1 + m.bit_length()
mask = (1 << bitlen) - 1
return '{0:0{1}b}'.format(n & mask, bitlen)
for i in (-10, -3, 0, 3, 10):
print('{:3}: {}'.format(i, twos_complement(i)))
print('- ' * 30)
for i in range(-15, 16):
print(i, twos_complement(i))
输出
-10: 10110
-3: 101
0: 0
3: 011
10: 01010
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-15 10001
-14 10010
-13 10011
-12 10100
-11 10101
-10 10110
-9 10111
-8 1000
-7 1001
-6 1010
-5 1011
-4 100
-3 101
-2 10
-1 1
0 0
1 01
2 010
3 011
4 0100
5 0101
6 0110
7 0111
8 01000
9 01001
10 01010
11 01011
12 01100
13 01101
14 01110
15 01111
工作原理
Python使用二进制补码的修改形式来表示整数. Python整数没有大小限制,因此负整数的行为就好像前导1位的无限个数一样,如关于按位运算符的Python Wiki文章.
How it works
Python uses a modified form of two's complement to represent integers. Python integers have no size limit, so negative integers behave as if they have an infinite number of leading 1 bits, as explained in the Python Wiki article on Bitwise Operators.
int.bit_length
方法告诉我们表示一个数字所需的最少位数,我们希望再加上一位,以便所有非负数都以0开头,所有负数都以1开头.我们需要稍作修改,以确保格式-2**n
的数字只会得到一个前导一位,我们通过在计算位长时对所有负数加1来做到这一点.
The int.bit_length
method tells us the minimum number of bits required to represent a number, we want one more bit than that so that all our non-negative numbers will start with 0 and all the negative numbers start with a 1. We need to modify that slightly to ensure that numbers of the form -2**n
will only get a single leading one bit, we do that by adding 1 to all the negative numbers when calculating the bit length.
要选择我们想要的位,我们需要适当长度的位掩码.如果位长度为4,则我们希望掩码为1111 = 2**4 - 1
;我们可以使用幂运算来计算它,但是使用位移更有效:(1 << bitlen) - 1
.然后,我们执行按位与运算n & mask
以选择所需的位.幸运的是,当执行屏蔽操作时,Python给我们提供了一个非负数. :)
To select the bits we want we need a bit mask of the appropriate length. If the bit length is 4, we want a mask of 1111 = 2**4 - 1
; we _could calculate it by using exponentiation, but it's more efficient to use bit shifting: (1 << bitlen) - 1
. We then do the bitwise AND operation n & mask
to select the bits we want. Fortunately, Python gives us a non-negative number when we perform such masking operations. :)
最后,我们使用.format
方法将结果整数转换为字符串.我们使用嵌套格式规范,因此我们可以动态指定输出字符串的正确长度.在
Finally we convert the resulting integer to a string using the .format
method. We use a nested format specification so we can dynamically specify the correct length of the output string. In
'{0:0{1}b}'.format(n & mask, bitlen)
格式规范的第一个0表示我们正在转换参数列表(n & mask
)中的0 arg的值,:0{1}b
表示要将其转换为二进制,并在必要时用前导零填充,使用参数列表(bitlen
)中的1 arg的值作为字符串的总长度.
the first 0 of the format spec says that we're converting the value of the 0 arg in the argument list (n & mask
), the :0{1}b
says to convert it to binary, padded with leading zeroes if necessary, using the value of the 1 arg in the argument list (bitlen
) as the total string length.
您可以在格式字符串中了解嵌套格式规范文档的语法部分:
这篇关于两个补码的Python(尽可能少的位)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!