计算机中位运算揭秘——补码、原码
一、概述
在计算机系统中,数值一律用补码来表示(存储)。
主要原因:使用补码,可以将符号位和其它位统一处理;同时,减法也可按加法来处理。另外,两个用补码表示的数相加时,如果最高位(符号位)有进位,则进位被舍弃。
原码:原码表示法在数值前面增加了一位符号位(即最高位为符号位),该位为0表示正数;该位为1表示负数,其余位表示数值的大小。
二、求给定数值的补码表示分以下两种情况
正数的补码:即为其原码。
负数的补码:取其绝对值的原码按位取反再加1,即是此负数的补码。
注意:同一个数字在不同的补码表示形式里头,是不同的。比方说-15的补码,在8位2进制里头是11110001,然而在16位2进制补码表示的情况下,就成了1111111111110001。
【例1】求-7(8位2进制中)的补码。
+7的原码(00000111)→按位取反(11111000)→加1(11111001)
所以-7补码是11111001
【例2】求20(8位2进制中)的补码。
20的原码(00010100)
所以20补码是00010100
三、给定补码,求补码所表示的(十进制)数值
1:如果给定的补码形式,是以0开头,则说明此补码表示的是一个正数,直接把此二进制换算成10进制就行。
2:如果给定的补码形式,是以1开头,则说明此补码表示的是一个负数;只需要对此补码按未取反,再对其加1,然后把得到的二进制换算成10进制,得到的就是此补码表示的数值的绝对值,加上负号,就是表示的数值。
【例3】求补码00010110表示的(十进制)数值。
00010110→以0开头,直接转换成十进制数→22
所以此补码表示的数值是22.
【例4】求补码10110010表示的(十进制)数值。
10110010 →以1开头,按位取反→01001101 →加1 →01001110 → 直接转换成十进制数 →78
所以此补码表示的数值是-78.
四、位运算
在计算机中对数值进行计算时,都是以数值的补码进行的。
在计算机系统中,有如下几种位运算(以java语言为例):
1:~ 取反运算符(NOT) 一元运算
2:& 与运算符 (AND) 二元运算
3:| 或运算符 (OR)
4:^ 异或运算符 (XOR)
5:<< 左移位运算符
6:>> 右移位运算符
【例5】
public class Test1{
public static void main(String[] args){
byte aByte = (byte)0x90; // byte类型二进制补码形式
int aInt = 0x90; // int类型的二进制补码形式
System.out.println(aByte);
System.out.println(aInt);
}
输出:
-112
144
分析:
1:对于变量aByte,因为它是byte类型,所以变量aByte的补码是八位的,展开即:10010000;所以变量表示的数值是负数,即-112。
2:对于变量aInt ,因为它是int类型,所以变量aInt的补码32位的,展开即:00000000000000000000000010010000;所以变量表示的数值正数,即为144。
【例5】
public class Test2{
public static void main(String[] args){
int aInt = 5;
System.out.println(~aInt); // 输出按位取反后的数值
}
输出:
-6
分析:
2:对于变量aInt ,因为它是int类型,所以变量aInt的补码32位的,即:00000000000000000000000000000101。
而00000000000000000000000000000101→ 按位取反→ 11111111111111111111111111111010(也是补码)。
由于按位取反后获得的补码是11111111111111111111111111111010,所以变量aInt按位取反后得到的数值是一个负数;然后计算新的补码所表示的数值。
11111111111111111111111111111010→ 按位取反→ 00000000000000000000000000000101→ 加1 → 00000000000000000000000000000110 → 6
所以变量aInt按位取反后的数值是-6。
对于其他的位运算,大家也可以按照此方式进行换算(需要注意数据类型的所占的位数)。