原码
原码即在原有二进制数字前增加一位符号位,正数符号位为: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;然后再进行相应的运算。
运算符优先级
运算符在参与运算的工作中,应注意运算符的优先级
- 本文链接: https://www.sunce.wang/archives/ji-suan-ji-ji-chu-zhi-yun-suan
- 版权声明: 本博客所有文章除特别声明外,均采用CC BY-NC-SA 3.0 许可协议。转载请注明出处!