为什么位运算(~0);
会输出-1?在二进制中,非0应该是1。为什么呢?
你其实已经非常接近了。
在二进制中,非0的数字应该是1.
没错,在我们谈论一个比特时,这绝对是正确的。
然而,一个值为0的整型实际上由32位全0组成!~
会将所有32个零反转为32个一。
System.out.println(Integer.toBinaryString(~0));
// prints "11111111111111111111111111111111"
这是数字 -1
的二进制补码表示。
同样地:
System.out.println(Integer.toBinaryString(~1));
// prints "11111111111111111111111111111110"
换句话说,对于使用二进制补码表示的32位无符号int
,~1 == -2
。
进一步阅读:
~
~x
等于(-x)-1
"您实际上表达的是0x00000000,这导致了0xFFFFFFFF。对于Java中的(有符号)int类型,这意味着-1。
您可以想象带符号数的第一位为 -(2x-1),其中x是位数。
因此,对于一个8位的数字,每个位(从左到右顺序)的值如下:
-128 64 32 16 8 4 2 1
现在,在二进制中,0显然是所有的0:
-128 64 32 16 8 4 2 1
0 0 0 0 0 0 0 0 0 = 0
当您执行按位取反运算符~
时,每个0都会变为1:
-128 64 32 16 8 4 2 1
~0 1 1 1 1 1 1 1 1
= -128+64+32+16+8+4+2+1 == -1
这对于理解溢出也是有帮助的:
-128 64 32 16 8 4 2 1
126 0 1 1 1 1 1 1 0 = 126
+1 0 1 1 1 1 1 1 1 = 127
+1 1 0 0 0 0 0 0 0 = -128 overflow!
~
是一种位运算符。~0 = 1 which is -1 in 2's complement form
http://en.wikipedia.org/wiki/Two's_complement
以下是二进制补码形式的一些数字及其按位取反 ~
(在它们下方):
注:二进制补码是一种用于表示带符号整数的方法。0 1 1 1 1 1 1 1 = 127
1 0 0 0 0 0 0 0 = −1280 1 1 1 1 1 1 0 = 126
1 0 0 0 0 0 0 1 = −1271 1 1 1 1 1 1 1 = −1
0 0 0 0 0 0 0 0 = 01 1 1 1 1 1 1 0 = −2
0 0 0 0 0 0 0 1 = 11 0 0 0 0 0 0 1 = −127
0 1 1 1 1 1 1 0 = 1261 0 0 0 0 0 0 0 = −128
0 1 1 1 1 1 1 1 = 127
因为~
不是二进制反转,而是按位反转。二进制反转应该使用!
,并且只能(在Java中)应用于布尔值。
在标准的二进制编码中,0表示全为0,~
表示按位取反。所有的1(通常情况下)对于有符号整数类型来说是-1。因此对于一个有符号字节类型:
0xFF = -1 // 1111 1111
0xFE = -2 // 1111 1110
...
0xF0 = -128 // 1000 0000
0x7F = 127 // 0111 1111
0x7E = 126 // 0111 1110
...
0x01 = 1 // 0000 0001
0x00 = 0 // 0000 0000
这是二进制反转,而在二补数中,-1是0的二进制反转。
这里的0不是一个位,而是一个字节(至少;或更多)- 00000000。使用按位或运算,我们将得到11111111。它作为有符号整数的值为-1...
对于32位有符号整数
~00000000000000000000000000000000=11111111111111111111111111111111
(即-1)
我认为真正的原因是波浪号(~)是二进制补码。
Javascript将字符波浪号(~)指定为二进制补码,尽管在大多数编程语言中,波浪号表示一的补码的位取反。
x ^ 1
。 - kennytm