按位 NOT

~运算符将翻转数字中的所有位。由于计算机使用有符号数表示 - 最值得注意的是,二进制补码表示编码负二进制数,其中负数用前导(1)而不是前导零(0)写入。

这意味着如果你使用 8 位来表示二进制补码数,则可以将 0000 00000111 1111 的模式表示为 0 到 127 之间的数字,并保留 1xxx xxxx 来表示负数。

八位二进制补码数

无符号值 二进制补码值
0000 0000 0 0
0000 0001 1 1
0000 0010 2 2
0111 1110 126 126
0111 1111 127 127
1000 0000 128 -128
1000 0001 129 -127
1000 0010 130 -126
1111 1110 254 -2
1111 1111 255 -1

实质上,这意味着虽然 1010 0110 的无符号值为 166(通过添加 (128 * 1) + (64 * 0) + (32 * 1) + (16 * 0) + (8 * 0) + (4 * 1) + (2 * 1) + (1 * 0) 得到),但它的二进制补码值为 -90(通过添加 (128 * 1) - (64 * 0) - (32 * 1) - (16 * 0) - (8 * 0) - (4 * 1) - (2 * 1) - (1 * 0) 得到,并补充该值)。

通过这种方式,负数范围可以达到 -128(1000 0000)。零(0)表示为 0000 0000,减 1(-1)表示为 1111 1111

但总的来说,这意味着~n = -n - 1

# 0 = 0b0000 0000
~0
# Out: -1
# -1 = 0b1111 1111
    
# 1 = 0b0000 0001
~1
# Out: -2
# -2 = 1111 1110

# 2 = 0b0000 0010
~2
# Out: -3
# -3 = 0b1111 1101

# 123 = 0b0111 1011
~123
# Out: -124
# -124 = 0b1000 0100

注意,当应用于正数时,此操作的总体效果可以归纳为:

~n -> -|n+1|

然后,当应用于负数时,相应的效果是:

~-n -> |n-1|

以下示例说明了最后一条规则……

# -0 = 0b0000 0000
~-0
# Out: -1 
# -1 = 0b1111 1111
# 0 is the obvious exception to this rule, as -0 == 0 always
    
# -1 = 0b1000 0001
~-1
# Out: 0
# 0 = 0b0000 0000

# -2 = 0b1111 1110
~-2
# Out: 1
# 1 = 0b0000 0001

# -123 = 0b1111 1011
~-123
# Out: 122
# 122 = 0b0111 1010