在计算机中,内部数据的处理是以补码的形式来进行处理的,因此研究清楚补码的相关情况就显得非常重要。
既然,计算机内 部处理的基础是以补码形式,所以所有的运算都和补码会有所纠结的。
位运算也不例外……
因此我们先从基础的补码开始总结
说起补码,就不得不牵扯到原码和反码
原,反,补得关系;
我们的计算机是以2进制处理的,所以我们通常遇到的整型就要先转化为二进制;
将十进制→二进制的方法
大家想必还记得,我还是废上几句话吧!
比如说是整型的正数。用次数除以2,然后再将商继续除以2,直到商的值为0时,再将各次所得的余数从下到上以从左到右的顺序排列即可。
比如:
98;
98/2=49……0;
49/2=24……1;
24/2=12……0;
12/2=6……0;
6/2=3……0;
3/2=1……1;
1/2=0……1;
那么98 的二进制就为:1100010;
负数的二进制就是在前面加上负号;
-98就为:-1100010;
此时得到的二进制就为原码;
反码:
正数的反码就是它自己,也就是这个数的原码。
负数的反码就是将它原码前的负号去掉,然后将此负数的最高位变为1,其余的值全部取反。即1变为0,0变为1。
如:
原码:-00010111;
反码: 11101000;
补码:
正数的还是为它本身的原码,即正数的话,原码,反码,补码是一伙的。
负数的补码将最高位变为1,再将其它的位数在末尾加上1,然后就是此数的补码;
譬如:
原码:-00010100;
补码: 10010101;
现在就应该说说位运算的相关情况了。
分类;
位与运算、位或运算、位异或运算、位取反运算、左移运算、右移运算。
位与运算:
位与运算的运算符号为:&与c语言中的&&正好是一半。
例:已知,a=-1,b=10。求a&b。
先得到a的二进制为原码:-00000001; 补码: 1000 0010
b的二进制为原码:00001010; 补码:00001010;
将待求的数值以各自的补码形式的各个位对应相乘,遵循逻辑运算的相关算法;得出的结果也为补码形式;
1000 0010(补码)
0000 1010(补码)
×
---------------------
0000 0010(补码)=2;
所以:a&b=2;
位或运算;
符号:|与c语言的或符号(||)相比较少了一竖。
遵从的规则和位与运算差不多,不同点在于它们的各位对应相比较如果有一个1的话,那么它们对应的这个位的结果就为1;
1000 0010(补码)
0000 1010(补码)
|
---------------------
1000 1010(补码);
异或运算:
符号:^;
与以上两者的区别在于,对应的为相比较如果不一样时,则结果就为1;否则就为0;
1000 0010(补码)
0000 1010(补码)
^
---------------------
1000 1000(补码);
位取反运算;
符号:~;
规则将各个位不管最高位是1或0;即不管为正数还是负数全部取反,即1变为0,0变为1。
1000 0010(补码)
~
---------------------
0111 1101(补码);
左移运算;
符号:<<;
A<<B;此意为将A的补码向左移动B位;最高位的1或0;不管,即不管正负。再在右边补上0,移动了几个位置补上几个位置。
比如:
A<<3;
1111 1001
将A向左移动3个位置;
为: 1100 1000;
右移运算;
符号:
>>
A>>B;
和上面差不多;只不过是这个东东是需要考虑符号的即最高位不管怎么移动,总是1;
比如:
A>2;
向右移动2位。
1001 1100;
1010 0111;