位运算以及实际应用

位运算

计算机中的数在内存中都是以二进制形式进行存储的 ,而位运算就是直接对整数在内存中的二进制位进行操作,因此其执行效率非常高,在程序中尽量使用位运算进行操作,这会大大提高程序的性能。


符号 描述 运算规则 实例(以四位二进制数为例)
& 两个位都为1时,结果才为1。 0001&0001=1,0001&0000=0,0000&0000=0000
| 两个位都为0时,结果才为0。 0001|0001=0001,0001
^ 异或 两个位相同为0,相异为1。 0001∧0001=0000,0001∧0000=1,0000∧0000=0
~ 取反 0变1,1变0。 ∼0=1,∼1=0
<< 左移 各二进位全部左移若干位,高位丢弃,低位补0。 0001<<k=0100,k=2,k kk是左移的位数,这里k = 2 k=2k=2
>> 右移 各二进位全部右移若干位,对无符号数,高位补0,有符号数,右移补1 11。 0100>>k=0001,k=2,k kk是右移的位数,这里k = 2 k=2k=2

异或可以看作不进位相加

如1^7 即001^111,将每一位相加,但是1+1不进位.

001

111

110

此时结果就为110,即6


异或满足交换律和结合律

a^b = b^a

a(bc) = (ab)c

可以通过上面的不进位相加来理解,因为不进位,所以可以直接将每一个数的每一位相加,不管顺序如何变,结果是不会变的。


** 异或运算的性质 **

a ^ 0 = a

a ^ a = 0

可以将一个二进制数代入理解


左移

二进制的左移相当于十进制的乘2,右移同理


实际应用

交换数据

a = x , b = y,交换a,b的值

  • 正常方法
tmp = a;
a = b;
b = tmp;

需要一个中间变量tmp来存储其中一个数的值,才能交换。

  • 使用异或
a = a ^ b;        // a = x ^ y 
b = b ^ a;        // b = y ^ x = y ^ x ^ y = x
a = a ^ b;        // a = a ^ b = x ^ y ^ x = y

根据异或的性质可以实现,不需要另外的数来实现交换,优化了空间复杂度,且位运算相比算术运算要快。


找到二进制数最右边的 1

如1000100,即找到从左往右第五位的 1

a = 1000100;
b = a & ( ~a + 1 )
//            a = 1000100
//           ~a = 0111011   按位取反
//       ~a + 1 = 0111100   
//a & ( ~a + 1) = 0000100   与: 都为 1 时才结果为 1

实例: 给出一个二进制数N,求出该数有几个 1

int count = 0 ;

while ( N != 0){
    int rightone = N & ( ~N +1 );   //得到最右边的 1 
    count++;
    N ^= rightOne;    //相与 除去最右边的1 
}   //循环直到N == 0

数组中有两个数出现了奇数次 , 其他数都为偶数次 , 求这两个数

设数组arr中有a,b两个数为奇数次,其余为偶数次,求a,b

int eor = 0;

for(int i = 0; i < arr.length ; i++ ){
    eor ^= arr[i];
}
//eor与整个数组异或,因为两个相同的数异或为0,所以偶数次的数可直接消掉,奇数次的数也只会剩下a, b
//所以 eor = a ^ b , 且不等于 0 
//所以 a != b ,eor 上必然有一位数为 1
//通过这一位可将数组分为两个部分 , 这位为0,或者这位为 1 ,而a,b也会被分别分到这两部分

//通过上面例子的方法可找到这一位数rightOne
int rightOne = eor & ( ~eor + 1 );
//rightOne 为 eor最右边的 1

int onlyOne = 0;
for(int i = 0; i < arr.length; i++ ){
    if( arr[i] & rigthOne != 0){    // 通过rightOne将数组分为两部分, 将这部分的所有数异或,偶数次的数依旧不会影响,最后只剩下a,b其中一个数,这里用onlyOne表示
        onlyOne ^= arr[i];
    }
    //另一个数着用eor ^ onlyOne 即可求出
}
posted @ 2023-01-11 13:40  Criollo  阅读(183)  评论(0)    收藏  举报