您的位置:首页 > 编程语言 > C语言/C++

C++: 位操作

2016-05-07 11:29 330 查看
使用位操作加快运行

位运算的知识

有效的计算2乘以8的方法
快速求取一个整数的7倍

实现位操作求两个数的平均值
引申利用位运算计算数的绝对值

不用除法操作符实现两个正整数的除法
方法一

方法二递归求解

方法三移位操作

引申1用逻辑运算实现加法运算

引申2如何只用逻辑运算实现乘法运算

位运算的知识

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

(2)获取整数n的二进制中最后一个 1:n&(-n) 或者 n&~(n-1)。例如,n = 010100, 则 -n = 101100,n&(-n) = 000100

(3)去掉正数n的二进制总的最后一个1:n&(n-1),如 n=010100, n-1 = 010011, n&(n-1)=010000

有效的计算2乘以8的方法

虽然直接进行乘法操作符运算也可以进行2*8,但是这种方法并非最优,通过移位的方法会比较高效。将一个数左移n位,相当于乘以了2的n次方。

常规的乘法运算也可以实现,但CPU直接支持位运算,效率最高,所以操作最有效的方法是2<<3

快速求取一个整数的7倍

( X < < 3 ) - X


注意:由于 -的优先级高于 << 所以不能去掉括号,否则结果不正确

实现位操作求两个数的平均值

求解平均数的方法就是将两者相加,然后除以2,以变量x与y为例,两者的平均数为(x+y)/2.

但是采用上述方法,会存在一个问题,当两个数比较大时,如两者的和大于了机器位数能够表示的最大值,可能会存在数据溢出的情况,而采用位运算的方法则可以避免这一问题,
(x&y)+((x^y)>>1)
就是求解变量x与y的平均数,且位运算相比除法运算,效率更高。

对于表达式
(x&y)+((x^y)>>1)
中,
x&y
表示的是取出x与y二进制位数中都为1的所有位,
x^y
表示的是x与y中有一个为1的所有位,右移1位相当于执行除以2运算。

整个表达式实际上可以分为两部分,第一部分是都为1的部分,因为相同,所以直接相加即可;而第二部分是x为1,y为0的部分以及x为0,y为1的部分,两部分加起来再除以2,然后跟前面的相加就可以表示两者的平均数了。

引申:利用位运算计算数的绝对值

对一个负数,右移31位后变成 0xffffffff

对一个正数,右移31位后变成0x00000000

而0xffffffff^x + x = -1 ;因为1011^1111 = 0100,任何数与1111异或,实质是把x的0和1进行颠倒计算。

如果用变量y表示x右移31位,(x^y)-y 则表示的是x的绝对值

不用除法操作符实现两个正整数的除法

方法一:

根据除法运算的原理进行减法操作,对除数循环减去被除数,减一次结果加一,直到刚好减为0或余数小于被除数为止

int div( int a, int b )
{
int result = 0;
if( b==0 )
{
cout << "除数不能为0" << endl;
return result;
}
while( a>b )
{
result++;
a = a-b;
}
return result;
}


方法二:递归求解



方法三:移位操作





引申1:用逻辑运算实现加法运算

实现两个正整数相加,一般直接使用加号运算符即可。根据题目中的要求,与上例中的方法二类似,可以通过移位操作符来进行正整数的加法运算。例如,5与7求和,转换为二进制求和为101与111求和,其二进制结果为1100.对于二进制的加法而言,1+1=0, 1+0=1, 0+0=0,通过对比位运算中的异或方法,不难发现,此方法与位运算中的异或类似。那么第一个数值就是:tempNum1 = num1^num2;0+0的进位是0,0+1的进位是0,只有1+1的进位是有效的,该思路与位运算的&运算相似,所以可以先 num1&num2,由于进位是进到高一位的,与<<运算很相似,同时num1和num2相互&之后,如果结果为0,那么久不存在进位,运算完成,所以可以用递归的思想实现。



引申2:如何只用逻辑运算实现乘法运算

此乘法,不大懂。。。



内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: