位运算相关总结

按位与运算符(&)

参加运算的两个数据,按二进制位进行“与”运算

运算规则:两位同时为1结果才为1,否则为0.

 

负数按补码形式参加按位与运算

“与运算”的特殊用途:

(1)清零。如果想将一个单元清零,即使其全部二进制位为0,只要与一个各位都为0的数值相与,结果为0.

(2)取一个数中指定位

方法:找一个数,对应X要取的位,该数的对应位为1,其余位为0,此数与X进行“与运算”可以得到x中的指定位。

 

按位或运算符(|

特殊作用:

(1)常用来对一个数据的某些位置1.

方法:找到一个数,对应X要置1的位,该数的对应位为1,其余位为0,。此数与x相或可使x中的某些位置1.

例:将x=10100000的低4位置1,用x|0000 1111=1010 1111可得到。

 

异或运算符(^

参加运算的两个数据,按二进制位进行“异或”运算

运算规则:参加运算的两个对象,如果两个相应位为“异”(值不同),则该位结果为1,否则为0

 

特殊作用:

(1)使特定位翻转找一个数,对应X要翻转的各位,该数的对应位为1,其余位为0,此数与X对应位异或即可。

例:x=10101110,使x4位翻转,用x^0000 1111=1010 0001即可得到。

(2)0相异或,保留原值,X^00000000=1010 1110

 

按位异或其实就是不进位加法,如1+1=0,0+0,1+0=1.

异或的几条性质:

1. 交换律

2. 结合律( a ^ b ) ^ c == a ^ ( b ^ c )

3. 对于任何数x,都有x^x=0,x^0=x

4. 自反性:a ^ b ^ b = a ^ 0 = a;

 

异或运算最常见于多项式除法,不过它最重要的性质还是自反性:A XOR B XOR B = A,即对给定的数A,用同样的运算因子(B)作两次异或运算后仍得到A本身。这是一个神奇的性质,利用这个性质,可以获得许多有趣的应用。 例如,所有的程序教科书都会向初学者指出,要交换两个变量的值,必须要引入一个中间变量。但如果使用异或,就可以节约一个变量的存储空间: 设有A,B两个变量,存储的值分别为ab,则以下三行表达式将互换他们的值 表达式 (值) :

 

a=a^b;

b=b^a;

a=a^b;

 

应用举例:

1~1000放在1001个元素的数组中,只有唯一的一个元素值重复,其他均只出现一次。每个数组元素只能访问一次,设计一个算法,将它找出来;不用辅助存储空间,能否设计一个算法实现?

 

解法一:把所有数加起来,减去1+2+……+1000的和。但问题是如果数列过大,则可能会导致溢出。

 

解法二:将所有数全部异或,得到的结果与1^2^3^^1000的结果进行异或,得到的结果就是重复数。

 

左移运算符(<<

将一个运算对象的各二进制位全部左移若干位(左边的二进制位丢弃,右边补0)。

例:a=a<<2a的二进制位左移2位,右补0,左移1位后a=a*2

 

 

右移运算符(>>

将一个数的各二进制全部右移若干位,正数左补0,负数左补1,右边丢弃。

操作数每右移一位,相当于该数除以2.

例如:a=a>>2a的二进制位右移2位,左补0 or 1得看被移数是正还是负。

 

符合赋值运算符:

&=   例:a &=b       相当于a=a& b

 

|=   例:a |=b       相当于a=a |b

 

>>=  例:a >>=b      相当于a=a>> b

 

<<= 例:a<<=b      相当于a=a<< b

 

^=   例:a ^= b      相当于a=a^ b

 

 

 

不同长度的数据进行位运算

如果两个长度不同的数据进行位运算时,系统会将二者按右端对齐,然后进行位运算。

 

“与”运算为例:

如果一个long类型数据与一个int类型数据进行“与”运算,右端对齐后,左边不足的位依下面三种情况补足,

(1)如果整型数据为正数,左边补160

(2)如果整型数据为负数,左边补161

(3)如果整型数据为无符号位,左边也补160

 

位运算:将一个字符型二进制数字转换成10进制

int change(char *st)

{

     int num = 0;

     while (*st)

         num = (num << 1) + (*st++ - '0');

     return num;

}

int main()

{

    char *pbin = "01001001";

    change(pbin);

    printf("%d", change(pbin));

}

                     位操作的运用

1. 奇偶性的判断

对于二进制表示来说,其最右位为1则该数为奇数,最右位为0则该数为偶数。

int a;

cin>>a;

if( a & 1)

   cout<<”奇数”<<endl;

if( ( a & 1 ) ==0)

   cout<<”偶数”<<endl;

2. 不借助变量交换两个数

a=a^b;

b=a^b;

a=a^b;

 

3. 取相反数

将正数n变为-n,将负数n变为-n

将整数取反加1即可得到相反数:

常见等式:- n = ~ ( n - 1 ) = ~ n + 1

 

例子:求某整数的绝对值

int  my_abs(int  num)

{

     if ( num < 0 )

{

   return  ~num + 1;//取反加一的到相反数

}

return num;

}


 

4. 整数二进制表示中最右边的1

获取整数二进制表示中最右侧的1n & (-n)等价于n & ~(n-1)

例如,n=1100,-n=0100,那么n & ( -n )=0100,这样就获取到了二进制表示中最右侧的1

去除整数二进制表示中最右侧的1n & (n-1)

例如,n=1100,n-1=1011,那么n & (n-1)=1000,这样就去除了二进制表示中最右侧的1

 

5.32位系统某数右移/左移32位或更多位

在移位运算时,byteshortchar类型移位后的结果会变成int类型,对于byteshortcharint进行移位时,规定实际移动的次数和32的余数,也就是移位33次和移位1次得到的结果相同。

 

位运算相关题目

1、二进制中1的个数

用到了n & (n - 1)

(1)方法一:参考文章:整数的二进制表示中1的个数

      方法二:二进制位的翻转和二进制表示中1的个数

 

(2) 输入两个数AB,输出将A转换为B所需改变的二进制的位数。

方法:首先,A异或B得到的是AB中不相同位数组成的数,然后再求这个数二进制表示中1的个数,即为所求。

2、位操作的加减运算(用位操作实现加减)

加法和减法相似,因为根据异或的自反性,a+b也就相当于a+(-b);  相反数就是取反加一。

//1.加法操作
int binaryadd(int a, int b)
{
	int ca;
	int add;
	do
	{
		add = a^b;//得到本位的加法结果
		ca = (a&b) << 1;//得到该位对高位的进位值
		a = add;
		b = ca;
	} while (ca != 0);//循环直到某次运算没有进位,运算结束
	return add;
}

//2.减法操作
int  binarysub(int a, int b)//减法操作就是加上一个负数
{
	return binaryadd(a, binaryadd(~b, 1));
}


3、求两个数中较小的那个

 

y ^ ((x ^ y) & -(x < y))

分析:当x < y时,-(x < y)-1,其补码形式全为1,则(x ^ y) & -(x < y) = x ^ y,则上述表达式返回的是较小的数x

x >= y时,-(x < y)0,补码形式为全0,则(x ^ y) & -(x < y) = 0, 则表达式返回的是较小的数y

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值