我对~运算符有点困惑。代码如下:
~
a = 1 ~a #-2 b = 15 ~b #-16
字符串~是如何工作的?我想,~a应该是这样的:
~a
0001 = a 1110 = ~a
型为什么不呢?
icnyk63a1#
你说得对。这是一个two's complement整数表示的人工产物。在16位中,1表示为0000 0000 0000 0001。反转,你得到1111 1111 1111 1110,这是-2。类似地,15是0000 0000 0000 1111。反转,你得到1111 1111 1111 0000,这是-16。一般情况下,~n = -n - 1
0000 0000 0000 0001
1111 1111 1111 1110
0000 0000 0000 1111
1111 1111 1111 0000
~n = -n - 1
kyxcudwk2#
'~'运算符的定义是:“x的按位求逆定义为-(x+1)。它只适用于整数。“Python Doc - 5.5这句话的重要部分是,这是有关'整数'(也称为整数)。您的例子表示一个4位数。
'0001' = 1
字符串一个4位数的整数范围是'-8..0..7'。另一方面,你可以使用'无符号整数',不包括负数,你的4位数的范围是'0..15'。由于Python对整数进行操作,因此您所描述的行为是预期的。整数使用2的补码表示。对于4位数字,如下所示。
7 = '0111' 0 = '0000' -1 = '1111' -8 = '1000'
型如果你有一个32位的操作系统,Python使用32位来表示整数。你可以用以下命令来检查最大的整数:
sys.maxint # (2^31)-1 for my system
型如果你想为你的4位数返回一个无符号整数,你必须屏蔽。
'0001' = a # unsigned '1' / integer '1' '1110' = ~a # unsigned '14' / integer -2 (~a & 0xF) # returns 14
型如果你想得到一个无符号的8位数范围(0..255),而不是只是用途:
(~a & 0xFF) # returns 254
型
nimxete23#
看起来我找到了一个更简单的解决方案,可以实现所需的功能:
uint8: x ^ 0xFF uint16: x ^ 0xFFFF uint32: x ^ 0xFFFFFFFF uint64: x ^ 0xFFFFFFFFFFFFFFFF
字符串
uujelgoq4#
你也可以使用unsigned int(例如numpy包中的)来实现预期的行为。
>>> import numpy as np >>> bin( ~ np.uint8(1)) '0b11111110'
wooyq4lh5#
问题是应用~的结果所表示的数字没有很好地定义,因为它取决于用于表示原始值的位数。例如:
5 = 101 ~5 = 010 = 2 5 = 0101 ~5 = 1010 = 10 5 = 00101 ~5 = 11010 = 26
字符串然而,~5的二进制补码在所有情况下都是相同的:
two_complement(~101) = 2^3 - 2 = 6 two_complement(~0101) = 2^4 - 10 = 6 two_complement(~00101) = 2^5 - 26 = 6
型考虑到二进制补码是用来表示负值的,所以可以将~5看作其补码的负值-6。所以,更正式地说,为了得到这个结果,我们有:1.翻转0和1(相当于取1的补码)1.取二的补码1.应用负号如果x是一个n位数:
~x = - two_complement(one_complement(x)) = - two_complement(2^n - 1 - x) = - (2^n - (2^n - 1 - x)) = - (x + 1)
6g8kf2rb6#
这里是一个实现,任何人都希望在整数的语义二进制表示中实现 * 位数字的字面反转 *。例如,**0b110010-> 0b1101**而不是0b110010-> -0b110011,如~运算符。
0b110010
0b1101
-0b110011
def bit_invert(n: int) -> int: """Calculate the bitwise inverse of n. Doesn't do funky stuff with sign bits, like Python's built-in bitwise not. """ return n ^ ((1 << n.bit_length()) - 1)
>>> for i in range(16): ... print(i, bin(i), bin(bit_invert(i))) ... 0 0b0 0b0 1 0b1 0b0 2 0b10 0b1 3 0b11 0b0 4 0b100 0b11 5 0b101 0b10 6 0b110 0b1 7 0b111 0b0 8 0b1000 0b111 9 0b1001 0b110 10 0b1010 0b101 11 0b1011 0b100 12 0b1100 0b11 13 0b1101 0b10 14 0b1110 0b1 15 0b1111 0b0
6条答案
按热度按时间icnyk63a1#
你说得对。这是一个two's complement整数表示的人工产物。
在16位中,1表示为
0000 0000 0000 0001
。反转,你得到1111 1111 1111 1110
,这是-2。类似地,15是0000 0000 0000 1111
。反转,你得到1111 1111 1111 0000
,这是-16。一般情况下,
~n = -n - 1
kyxcudwk2#
'~'运算符的定义是:“x的按位求逆定义为-(x+1)。它只适用于整数。“Python Doc - 5.5
这句话的重要部分是,这是有关'整数'(也称为整数)。您的例子表示一个4位数。
字符串
一个4位数的整数范围是'-8..0..7'。另一方面,你可以使用'无符号整数',不包括负数,你的4位数的范围是'0..15'。
由于Python对整数进行操作,因此您所描述的行为是预期的。整数使用2的补码表示。对于4位数字,如下所示。
型
如果你有一个32位的操作系统,Python使用32位来表示整数。你可以用以下命令来检查最大的整数:
型
如果你想为你的4位数返回一个无符号整数,你必须屏蔽。
型
如果你想得到一个无符号的8位数范围(0..255),而不是只是用途:
型
nimxete23#
看起来我找到了一个更简单的解决方案,可以实现所需的功能:
字符串
uujelgoq4#
你也可以使用unsigned int(例如numpy包中的)来实现预期的行为。
字符串
wooyq4lh5#
问题是应用~的结果所表示的数字没有很好地定义,因为它取决于用于表示原始值的位数。例如:
字符串
然而,~5的二进制补码在所有情况下都是相同的:
型
考虑到二进制补码是用来表示负值的,所以可以将~5看作其补码的负值-6。
所以,更正式地说,为了得到这个结果,我们有:
1.翻转0和1(相当于取1的补码)
1.取二的补码
1.应用负号
如果x是一个n位数:
型
6g8kf2rb6#
这里是一个实现,任何人都希望在整数的语义二进制表示中实现 * 位数字的字面反转 *。
例如,**
0b110010
->0b1101
**而不是0b110010
->-0b110011
,如~
运算符。字符串
示例
型