理解Python中的按位NOT

问题描述 投票:0回答:3

我试图理解Python中的按位NOT。

我尝试了以下方法:

print('{:b}'.format(~ 0b0101)) 
print(~ 0b0101)

输出是

-110
-6

我尝试理解输出如下:

按位求反

0101
得到
1010
。当
1
处于最高有效位时,Python 将其解释为 2 的补码形式的负数,并且为了得到相应的小数,它进一步需要
1010
的 2 的补码,如下所示:

 1010
 0101  (negating)
 0110  (adding 1 to get final value)

因此它将其打印为

-110
,相当于
-6

我的这种解释正确吗?

python bit-manipulation bitwise-operators
3个回答
3
投票

你说对了一半..

该值确实由

~x == -(x+1)
表示(加一并反转),但其原因的解释有点误导。

二进制补码数字需要设置整数的MSB,如果数字可以是任意位数长(就像Python的情况),这有点困难。 python 内部保留一个单独的数字(但是对短数字有优化)来跟踪数字的长度。当您使用二进制格式

print
一个负整数时:
f'{-6:b}
,它只是在正值的二进制表示形式(一个的恭维)前面加上一个负号。否则,python将如何确定应该有多少个前导?正值是否应该总是有前导零来表明它们是正值?但在内部,它确实使用了二进制补码来进行数学计算。

如果我们考虑以 2 的补码表示带符号的 8 位数字(并显示所有数字),您的示例将变为:

~ 0000 0101:5
= 1111 1010:-6

简而言之,Python 正在执行正确的按位求反,但是负二进制格式数字的显示会产生误导。


2
投票

Python 整数是任意长的,所以如果你反转 0b0101,它将是 1111...11111010。 你写了多少个? 那么,4 位二进制补码 -6 是 1010,32 位二进制补码 -6 是 11111111111111111111111111111010。因此,任意长的 -6 理想情况下可以写为 -6。

检查当 ~5 被屏蔽以查看它代表的位时会发生什么:

>>> ~5
-6
>>> format(~5 & 0xF,'b')
'1010'
>>> format(~5 & 0xFFFF,'b')
'1111111111111010'
>>> format(~5 & 0xFFFFFFFF,'b')
'11111111111111111111111111111010'
>>> format(~5 & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFF,'b')
'11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111010'

负十进制表示是有意义的,您必须进行掩码以将表示形式限制为特定位数。


0
投票

ничего толком не объяснено。将“0b1”改为“-0b10”。 С минусом все понятно, последний левый бит, отвечающий за положительность числа и = 0 , инвертируется в единицу, а значит число становится отрицательным。 НО откуда у числа в двоичном представлении, слева от нуля добавляется единица, по идее должно быть '0b1' -> '-0b0', а самом деле '0b1' -> '-0b10' ??????

© www.soinside.com 2019 - 2024. All rights reserved.