位操作之求绝对值

来源:互联网 发布:海关数据是什么 编辑:程序博客网 时间:2024/05/20 14:43

今天继续学习了位操作,用位操作实现求一个数的绝对值:
对于一个整数a,如果是个正数就直接返回,但是如果是个负数呢?应该取反再返回,比如-5取反后应该是+5,然后返回。
在计算机中数都是用二进制来表示的,就是一串的0和1组合:
例如5的二进制表示为:0000 0101,
-5该如何表示,应该用补码来表示,就是,+5的二进制先按位取反,然后加1,如下:
先按位取反得: 1111 1010, 然后加1
加1以后为: 1111 1011 最高位表示符号 0位正,1为负
所以,我们求一个数的绝对值的时候,对于int(4字节)我们可以先把所求的数右移31位,求的改数的符号位,如果符号位为0,那么该数是整数,直接返回;如果是1,那么该数是负数,就按上面所说的,先按位取反,然后加1,返回。

对于移位操作来说,有算术移位和逻辑移位两种。对于左移来说没有区别,就是后面补0;但是对于右移来说不一样,算术右移是补符号位,就是说正数补0,但是负数要补符号位的话是1,这个要看系统了。而逻辑移位就是补0.
对于位操作来说,他们在c中运算优先级别比较低,应该尽量用括号()来保证运算顺序的正确性。

#include<stdio.h>int my_abs(int a){    int i ;    i = a>>31;//右移31位取得符号位    if(i == 0)//如果符号位是0,是正数,返回a    return a;    else//如果不是0    return (~a+1);//返回(~a+1)就是a先按位取反,然后加1}int main(){    int k =-100;    printf("%d\n",my_abs(k));    return 0;}

第二种方法:
用异或运算。异或就是说如果对应的二进制位不同,运算结果就是1,如果相同就为0:
1^1 = 0; 1^0=1;0^0=0。我们也可以看出,任何数与0异或是它本身,与它本身异或结果是0:就是说对于一个数a来说,下面的运算式正确的:a^0 = a;a^a = 0;
再说一下一个数a,如果与-1(负1)异或结果会是什么.我们可以先看一下+1和-1怎么表示:
+1 = 0000 0001;
-1 = 1111 1110 +1 =1111 1111;
我们可以看到-1就是二进制的所有位都是1.
我们再看看前面的异或运算:1^1 = 0; 0^1 = 1;所以一个单独的位和1异或就是把该位取反。
因为 -1 就是所有二进制位为1的数。所以一个数和 -1 异或的话,实际上就是 把该数 按位取反。
比如 5 = 0000 0101;

          5  = 0 0 0 0       0 1 0 1  ^     -1 =   1 1 1 1       1 1 1 1  -------------------------------------    =          1 1 1 1       1 0 1 0(已经按位取反了)

所以我们也可以用异或的方法求绝对值,不用任何库函数和判断语句。

#include<stdio.h>int my_abs2(int a){    int i ;    i = a>>31;//取得符号位    return ((a^i) -i);//如果i是0的话,那么(a^i)-i相当于(a^0)-0=a-0=a;                      //如果i是-1的话,那么(a^i)-i相当于(a^-1)-(-1)=(~a)+1,就和上一例一样了}int main(){    int k =-100;    //printf("%d\n",my_abs(k));    printf("--abs2----------------------------\n");    printf("%d\n",my_abs2(-1000));    return 0;}
0 0