原码

原码即在原有二进制数字前增加一位符号位,正数符号位为:0,负数符号位为:1。

例如:我们用8位二进制表示一个数:

11的原码: 0000 1011

-11的原码:1000 1011

原码的优点是简单直观,但是不便于参与运算。

例如 -1+1=0;但是利用原码直接进行运算结果为-2,显然是不对的。

-1表示:1000 0001

1表示: 0000 0001

结果: 1000 0010


反码

正数的反码与原码相同,负数的反码是符号位除外,其他位按位取反;

例如:

+0的反码:
+0的原码:0000 0000
+0的反码:0000 0000

-0的反码:
-0的原码:1000 0000
-0的反码:1111 1111

反码为计算补码的中间过程码。


补码

正数的补码与原码相同,负数的补码为其反码再加1;补码求原码即为再次取补码。

例如:

+0的反码:
+0的原码:0000 0000
+0的反码:0000 0000
+0的补码:0000 0000

-0的反码:
-0的原码:1000 0000
-0的反码:1111 1111
-0的补码:0000 0000

补码解决了计算中的符号问题,它使得符号位有了数学特征,还可以将减法转换为加法来运算;计算机元器件的特点实现补码与真值之间的转换非常容易。如下的计算过程实际都是补码再参与进行,正数的补码与原码相同,所以计算过程省略了转换过程。


按位与运算

与运算通常使用 & 表示;&表示按位与运算,&&表示逻辑与运算(短路与),运算规则如下:

0&0=0;0&1=0;1&0=0;1&1=1;负数是补码参与运算

例如: 7&5=?

7二进制表示: 0000 0111

5二进制表示: 0000 0101

7&5运算结果: 0000 0101

结果即为: 5

例如: 7&-5=?

-5二进制表示: 1000 0101

-5的补码: 1111 1011

7二进制表示: 0000 0111

进行运算:0000 0011

再取补码:0000 0011

7&-5运算结果: 0000 0011

结果即为: 3

&的特殊用途:

  • “清零”操作,一个数字想要实现各位都变成0,与一个各位数值都为0的数值相与,则可以实现
  • 获取数值中X位的数值是0还是1;则与X位是1,其余位都是0的值相与,即可获得结果。

例如,我想知道X的第2,3,4位是0还是1,则进行如下操作:

二进制X&0000 1110 = 0000 1010;我们可以从结果返推出,第2,4位是1,第3位是0。


按位或运算

或运算通常使用 | 表示;运算规则如下:

0|0=0;0|1=1;1|0=1;1|1=1;负数是补码参与运算

例如: 7|5=?

7二进制表示: 0000 0111

5二进制表示: 0000 0101

7|5运算结果: 0000 0111

结果即为: 7

例如: 7|-5=?

-5二进制表示: 1000 0101

-5的补码: 1111 1011

7二进制表示: 0000 0111

进行运算:1111 1111

再取补码:1000 0001

7|-5运算结果: 1000 0001

结果即为: -1

|的特殊用途:

通&用法类似,类似不过语义有些区别;当你希望将某个数字的X位置为1时,与一个该为是1,其余位是0的数值相与,即可实现。


按位异或运算

异或运算通常使用 ^ 表示;运算规则如下:

0^0=0;0^1=1;1^0=1;1^1=0;负数是补码参与运算

例如: 7^5=?

7二进制表示: 0000 0111

5二进制表示: 0000 0101

7^5运算结果: 0000 0010

结果即为: 2

例如: 7^-5=?

-5二进制表示: 1000 0101

-5的补码: 1111 1011

7二进制表示: 0000 0111

进行运算:1111 1100

再取补码:1000 0100

7^-5运算结果: 1000 0100

结果即为: -4

^的特殊用途:

  • 翻转特定位X的值,即实现特定位0变1,1变0;只要与一个特定位是1,其余位是0的数值进行^运算,即可实现。

  • 任何是与0进行^运算,结果为其原值。


取反运算

取反运算通常使用 ~ 表示;取反运算符的优先级高于算术运算符,比较运算符,逻辑运算符;运算规则如下:

正数取反运算:对数字进行二进制表示,(正数补码等于原码所以省略此描述:再取得二进制数的补码),对二进制数的每一位进行运算(包括符号位),即0变1,1变0,得到的数据为最终结果的补码,要想得到最终结果则需要再次取补码。

负数取反运算:对数字进行二进制表示,再取得二进制数的补码,对补码的每一位进行运算(包括符号位),即0变1,1变0,得到的数据为最终结果的补码,要想得到最终结果则需要再次取补码。

总结计算公式: ** ~a = - (a + 1) **

例如:

~7=?

7二进制表示:0000 0111

每一位取反 :1111 1000

取反码(省略):1000 0111

取补码:1000 1000

最终结果:-8

~-7=?

-7二进制表示:1000 0111

取补码:1111 1001

每一位取反 :0000 0110

取反码(省略):0000 0110

取补码:0000 0110

最终结果:6


左移运算

左移运算符通常使用 << 表示;运算规则如下:

将一个数字的二进制数的补码向左移动若干位,右边补0;

例如: 3<<2

3的二进制表示:0000 0011

左移两位:0000 1100

结果即为:12

例如: -3<<2

-3的二进制表示:1000 0011

原码取补码:1111 1101

左移两位:1111 0100

移位后取补码:1000 1100

结果即为:-12


右移运算

右移运算符通常使用 >> 表示;运算规则如下:

将一个数字的二进制数的补码向右移动若干位,正数左边补0,负数左边补1,右边丢弃;

例如:7>>2

7二进制表示: 0000 0111

右移两位: 0000 0001

结果即为:1

例如:-7>>2

-7二进制表示: 1000 0111

原码取补码:1111 1001

有符号右移两位:1111 1110

移位后取补码:1000 0010

结果即为:-2


无符号右移运算

将一个数字的二进制数的补码向右移动若干位,包括符号位无论正负左边补0右边丢弃;特殊说明:以上示例为了便于演示,忽略了操作系统位数,以及在不同编程语言中整数所占字节数

以下示例基于:JAVA语言中int类型

例如:7>>>2

7二进制表示:00000000 00000000 00000000 00000111

右移两位: 00000000 00000000 00000000 00000001

结果即为:1

例如:-7>>>2

-7二进制表示:10000000 00000000 00000000 00000111

原码取补码:11111111 11111111 11111111 11111001

右移两位: 00111111 11111111 11111111 11111110

移位后取补码:00111111 11111111 11111111 11111110

结果即为:1073741822


TIPS

不同长度的数据进行位运算,例如:int 类型与 long 类型的数值进行位运算时,位数较短的需要进行补位操作;正数左边补0,负数左边补1;然后再进行相应的运算。