刷题的时候看到python的二进制存储很有特点,在网上搜索半天也没看明白,特自己总结如下。
首先需要知道:
1.python存储一个数据是无限位的。
2.python正数是按源码存储的,1的源码是0b1,负数是按照补码存储的,-1的补码(即源码取反再加一)是0xff…ffffff(无数个f),二进制就是0b后面无数个1。
因为位数是无限的,所以我们怎么操作呢?
如果这个数字在-2^31到2*31-1之前,则对它进行截断,舍去此数字 32 位以上的数字:&0xffffffff。
这样-1就变成了0x00…000ffffffff
处理完之后怎么判断数字是正数还是负数呢?
首先可以这样 (a&0x80000000)>>31,如果是1,就是负数
或者可以这样 a <= 0x7fffffff,如果为False,就是负数
然后知道数字的正负了,该怎么得到他的大小呢?
经过&0xffffffff之后,得到正数的32位源码和负数的32位补码,正数可以直接输出了,负数再-(~x+1),取反加一再加个负号就得到所需负数了。
负数还有一种简单方法,我们把截取掉的32位之前的位数恢复出来,然后让python识别后输出。如果不把之前的位数恢复,python只会根据这32位输出(不会把某一位当成符号位)。例如print(-1 & 0xffff)会输出65535
# 以0xffff为例,0xffffffff同理
m = -234
print(-(((m&0xffff)^ 0xffff)+1))
# 手动操控补码输出,其中m&0xffff获得补码,然后取反加一,再加负号。+-优先级高于位运算
print( ~((m&0xffff)^0xffff) )
# 先m&0xffff截取,把16位之前的无限位数置0了,得到补码,
# 再^0xffff对16位取反之后对所有位取反(即除后16位之外,前面的位取反),
# 可以把16位之前的无限位数恢复至1,python自动根据补码输出
上面为两种实现方法,都会输出-234