位运算

118 阅读5分钟

十进制转化为二进制

截屏2022-09-03 下午5.24.03.png

11 = 1 * 2^0 + 1 * 2^1 + 0 * 2^2 + 1 * 2^3

原码、反码、补码

正整数原码、反码和补码一致 负整数的反码:符号位不变,其它位取反;补码:反码+1。

原码

将十进制的数用32位的二进制来表示

// 11的二进制
00000000 00000000 00000000 00001011

最高位:0表示正数,1表示负数

反码

  • 负整数的反码为:其原码的符号位不变,其它位取反。
  • 正整数的反码等于原码
// -11的二进制
10000000 00000000 00000000 00001011   原码
11111111 11111111 11111111 11110100   反码

补码

  • 负整数的补码为:反码 + 1
  • 正整数的补码等于原码
// -11的二进制
10000000 00000000 00000000 00001011   原码
11111111 11111111 11111111 11110100   反码
+1
11111111 11111111 11111111 11110101   补码

补码的作用

统一数字0的表示

使得+0和-0的二进制一致

由于正整数的原码、补码和反码表示一致。所以看看-0的原码、反码和补码。

// -0
10000000 00000000 00000000 00000000 -0原码
// 符号位不变,其它位取反
11111111 11111111 11111111 11111111 -0反码
// +1进一位就全为0
00000000 00000000 00000000 00000000 -0补码

简化加减法的运算

减法视为补码的加法

正整数相加用原码相加没有问题,但是负数用原码计算就不对,要用补码进行计算。

-6 10000000 00000000 00000000 00000110 原码
+5 00000000 00000000 00000000 00000101 原码
-11 10000000 00000000 00000000 00001011 错误


-6 10000000 00000000 00000000 00000110 原码
-6 11111111 11111111 11111111 11111001 反码
-6 11111111 11111111 11111111 11111010 补码
+5 00000000 00000000 00000000 00000101 补码
--------------------------------------
   11111111 11111111 11111111 11111111 补码
-1
--------------------------------------
   11111111 11111111 11111111 11111110 反码
-1 10000000 00000000 0000000  00000001 原码 正确

32位表示的整数范围

[-2^31, 2^31-1];

按位取反

对补码进行取反。

~9 = -10

//9
1001 原码
01001 补码
10110 取反
10101 反码
11010 原码 -10

左移(<<),有符号右移(>>),无符号右移(>>>)

左移:将二进制向左移动几位,低位补零。

左移和符号没有关系。

4:     00000000 00000000 00000000 00000100
4<<2:  00000000 00000000 00000000 00010000 4 * 2^2 = 16

-4:    11111111 11111111 11111111 11111100
-4<<2: 11111111 11111111 11111111 11110000111111111 11111111 11111111 11101111
取反:  10000000 00000000 00000000 00010000 -4*2^2 = -16

正数有符号右移和无符号右移是一样的 负数无符号右移高位补零

15:     00000000 00000000 00000000 00001111
15>>2:  00000000 00000000 00000000 00000011
15>>>2: 00000000 00000000 00000000 00000011  Math.floor(15 / 2^2)= 3
-15:    11111111 11111111 11111111 11110001 补码
-15>>2: 11111111 11111111 11111111 11111100 补码
减1:    11111111 11111111 11111111 11111011 反码
取反:   10000000 00000000 00000000 00000100 原码 Math.floor(-15/2^2) = -4

-15:    11111111 11111111 11111111 11110001 补码
-15>>>2: 00111111 11111111 11111111 11111100 补码 无符号高位补零
减1:     00111111 11111111 11111111 11111011
取反:   11000000 00000000 00000000 00000100

& | ^

&: 都为1为1

|: 有1为1

^: 相同为0,不同为1