C++位运算

本文深入探讨了位运算符的基本概念及其在计算机科学中的多种应用,包括移位运算、按位与、或、异或的操作及其实例。此外,还介绍了如何使用位运算进行整数的平均值计算、判断是否为2的幂、交换变量值、求绝对值等高级技巧。

移位运算 
要点 1 它们都是双目运算符,两个运算分量都是整形,结果也是整形。 
    2 " < <" 左移:右边空出的位上补0,左边的位将从字头挤掉,其值相当于乘2。 
    3 ">>"右移:右边的位被挤掉。对于左边移出的空位,如果是正数则空位补0,若为负数,可能补0或补1,这取决于所用的计算机系统。 
    4 ">>>"运算符,右边的位被挤掉,对于左边移出的空位一概补上0。 
位运算符的应用 (源操作数s 掩码mask) 
(1) 按位与-- & 
1 清零特定位 (mask中特定位置0,其它位为1,s=s&mask) 
2 取某数中指定位 (mask中特定位置1,其它位为0,s=s&mask) 
(2) 按位或-- | 
    常用来将源操作数某些位置1,其它位不变。 (mask中特定位置1,其它位为0 s=s|mask) 
(3) 位异或-- ^ 
1 使特定位的值取反 (mask中特定位置1,其它位为0 s=s^mask) 
2 不引入第三变量,交换两个变量的值 (设 a=a1,b=b1) 
   

 

目标 

操作 

操作后状态 

a=a1^b1  

a=a^b  

a=a1^b1,b=b1  

b=a1^b1^b1  

b=a^b  

a=a1^b1,b=a1  

a=b1^a1^a1  

a=a^b  

a=b1,b=a1  


二进制补码运算公式: 
-x = ~x + 1 = ~(x-1) 
~x = -x-1 
-(~x) = x+1 
~(-x) = x-1 
x+y = x - ~y - 1 = (x|y)+(x&y) 
x-y = x + ~y + 1 = (x|~y)-(~x&y) 
x^y = (x|y)-(x&y) 
x|y = (x&~y)+y 
x&y = (~x|y)-~x 
x==y:    ~(x-y|y-x) 
x!=y:    x-y|y-x 
x < y:    (x-y)^((x^y)&((x-y)^x)) 
x <=y:    (x|~y)&((x^y)|~(y-x)) 
x < y:    (~x&y)|((~x|y)&(x-y))//无符号x,y比较 
x <=y:    (~x|y)&((x^y)|~(y-x))//无符号x,y比较 


应用举例 
(1) 判断int型变量a是奇数还是偶数            
a&1  = 0 偶数 
      a&1 =  1 奇数 
(2) 取int型变量a的第k位 (k=0,1,2……sizeof(int)),即a>>k&1 
(3) 将int型变量a的第k位清0,即a=a&~(1 < <k) 
(4) 将int型变量a的第k位置1, 即a=a|(1 < <k) 
(5) int型变量循环左移k次,即a=a < <k|a>>16-k  (设sizeof(int)=16) 
(6) int型变量a循环右移k次,即a=a>>k|a < <16-k  (设sizeof(int)=16) 
(7)整数的平均值 
对于两个整数x,y,如果用 (x+y)/2 求平均值,会产生溢出,因为 x+y 可能会大于INT_MAX,但是我们知道它们的平均值是肯定不会溢出的,我们用如下算法: 
int average(int x, int y)  //返回X,Y 的平均值 
{    
    return (x&y)+((x^y)>>1); 

(8)判断一个整数是不是2的幂,对于一个数 x >= 0,判断他是不是2的幂 
boolean power2(int x) 

    return ((x&(x-1))==0)&&(x!=0); 

(9)不用temp交换两个整数 
void swap(int x , int y) 

    x ^= y; 
    y ^= x; 
    x ^= y; 

(10)计算绝对值 
int abs( int x ) 

int y ; 
y = x >> 31 ; 
return (x^y)-y ;        //or: (x+y)^y 

(11)取模运算转化成位运算 (在不产生溢出的情况下) 
        a % (2^n) 等价于 a & (2^n - 1) 
(12)乘法运算转化成位运算 (在不产生溢出的情况下) 
        a * (2^n) 等价于 a < < n 
(13)除法运算转化成位运算 (在不产生溢出的情况下) 
        a / (2^n) 等价于 a>> n 
        例: 12/8 == 12>>3 
(14) a % 2 等价于 a & 1        
(15) if (x == a) x= b; 
            else x= a; 
        等价于 x= a ^ b ^ x; 
(16) x 的 相反数 表示为 (~x+1) 

(17)求x转化为二进制之后包含1的数量

    int count = 0;

    while(x)

  {

    count++;

    x = x & (x - 1);

    }

最后得到的count 即为x转化为二进制之后包含1的数量


实例 

 

 

 

 

 

功能   

示例

位运算

去掉最后一位

(101101->10110)  

x >> 1  

在最后加一个0

(101101->1011010)  

x < < 1  

在最后加一个1

(101101->1011011) 

x < < 1+1  

把最后一位变成1

(101100->101101)  

x | 1  

把最后一位变成0

(101101->101100) 

x | 1-1  

最后一位取反

(101101->101100)  

x ^ 1  

把右数第k位变成1

(101001->101101,k=3)

x | (1 < < (k-1))  

把右数第k位变成0

(101101->101001,k=3)   

x & ~ (1 < < (k-1))  

右数第k位取反

(101001->101101,k=3)  

x ^ (1 < < (k-1))  

取末三位  

(1101101->101)  

x & 7  

取末k位

(1101101->1101,k=5) 

x & ((1 < < k)-1)  

取右数第k位

(1101101->1,k=4) 

x >> (k-1) & 1 

把末k位变成1

(101001->101111,k=4)  

x | (1 < < k-1)  

末k位取反

(101001->100110,k=4) 

x ^ (1 < < k-1)  

把右边连续的1变成0

(100101111->100100000) 

x & (x+1)  

把右起第一个0变成1

(100101111->100111111)  

x | (x+1)  

把右边连续的0变成1

(11011000->11011111)  

x | (x-1)  

取右边连续的1

(100101111->1111)

(x ^ (x+1)) >> 1  

去掉右起第一个1的左边

(100101000->1000) 

x & (x ^ (x-1))  

判断奇数

(x&1)==1  

判断偶数

(x&1)==0 

转载于:https://www.cnblogs.com/widerg/p/7287301.html

<think>好的,用户需要关于C++位运算的P1225题解或示例代码。首先,我需要确认P1225具体是哪道题,但可能用户指的是某个在线评测平台上的题目编号,比如洛谷或者力扣。不过,假设P1225是一个涉及位运算的问题,可能需要用位操作来高效解决。 接下来,我需要回忆常见的位运算题目类型,比如二进制操作、位掩码、状态压缩等。可能的题目可能涉及异或、移位、与或非操作。比如,可能是求某个数的二进制表示中1的个数,或者找出数组中只出现一次的数字,或者更复杂的问题。 用户可能希望得到详细的解题思路和C++代码示例。所以,我需要先构造一个假设的题目场景,或者如果记得具体的P1225题目内容,就按那个来。但如果没有具体信息,可能需要提供一个常见的位运算问题作为例子,比如“二进制中1的个数”或者“使用位运算实现加法”。 假设题目是“使用位运算实现两数相加而不使用+运算符”,这是一个常见的位运算问题。那么解题思路是:利用异或计算无进位和,利用与运算和左移计算进位,然后循环直到进位为0。 然后,我需要写出相应的C++代码,并解释每一步的作用。同时,生成相关问题,帮助用户进一步理解位运算的应用。 另外,用户提到“参考站内引用”,但这里没有给出具体引用来源,所以可能需要忽略这部分,或者假设没有引用需求。 总结步骤: 1. 确定题目需求(假设一个例子)。 2. 分析解题思路,使用位运算方法。 3. 编写C++代码示例并注释。 4. 生成相关问题,如优化方法、应用场景等。</think>### C++位运算实现两数相加(P1225类型问题示例) 假设题目要求:使用位运算实现两个整数的加法运算,不得使用`+`运算符。 #### 解题思路 1. 位运算加法原理: - 异或运算`^`:计算无进位和(对应位不同时结果为1) - 与运算`&` + 左移`<<1`:计算进位值(对应位同为1时产生进位) - 循环直到进位值为0时结束 2. 算法步骤: - 计算当前位的无进位和赋值给`a` - 计算进位值并赋值给`b` - 将`b`左移1位作为新的进位值 - 重复上述过程直至进位为0 #### 示例代码 ```cpp int add(int a, int b) { while (b != 0) { int sum = a ^ b; // 无进位和 int carry = (a & b) << 1; // 进位值 a = sum; b = carry; } return a; } ``` #### 代码说明 - 时间复杂度:$O(1)$(固定32次循环) - 空间复杂度:$O(1)$ - 关键操作:每次迭代将加法分解为无进位和与进位两部分处理
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值