我对~运算符有点困惑。代码如下:
~
a = 1~a #-2b = 15~b #-16
a = 1
~a #-2
b = 15
~b #-16
字符串~是如何工作的?我想,~a应该是这样的:
~a
0001 = a1110 = ~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'
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
'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 ^ 0xFFuint16: x ^ 0xFFFFuint32: x ^ 0xFFFFFFFFuint64: x ^ 0xFFFFFFFFFFFFFFFF
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'
>>> import numpy as np
>>> bin( ~ np.uint8(1))
'0b11111110'
wooyq4lh5#
问题是应用~的结果所表示的数字没有很好地定义,因为它取决于用于表示原始值的位数。例如:
5 = 101~5 = 010 = 25 = 0101~5 = 1010 = 105 = 00101~5 = 11010 = 26
5 = 101
~5 = 010 = 2
5 = 0101
~5 = 1010 = 10
5 = 00101
~5 = 11010 = 26
字符串然而,~5的二进制补码在所有情况下都是相同的:
two_complement(~101) = 2^3 - 2 = 6two_complement(~0101) = 2^4 - 10 = 6two_complement(~00101) = 2^5 - 26 = 6
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)
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 0b01 0b1 0b02 0b10 0b13 0b11 0b04 0b100 0b115 0b101 0b106 0b110 0b17 0b111 0b08 0b1000 0b1119 0b1001 0b11010 0b1010 0b10111 0b1011 0b10012 0b1100 0b1113 0b1101 0b1014 0b1110 0b115 0b1111 0b0
>>> 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
,如~
运算符。字符串
示例
型