位运算 之按位异或(xor)^ 操作

本文详细解析了按位异或运算的基本知识、原理、与按位否操作的关系,以及两个有趣的式子的应用。同时介绍了如何利用异或运算统计整数中1的奇偶性,并附带了求解数前导0个数的代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

按位异或运算

 俗称:xor运算

 

1xor的基本知识

 

我们来看看xor运算的机理:

 

1001011001011----àa

xor    1011010001110----àb

-------------------------

      0010001000101---àc

 

看了上面的式子,体会到异或运算的原理了吧,就是:0和1异或0都不变,异或1则取反。很容易理解,如果b中的某位为1,那么a xor b 的作用是在a相应的位进行取反操作。用通俗易懂的语言来讲就是xor运算通常用于对二进制的特定一位进行取反操作。

我们再看到上面那个计算式子,如果得到的结果c再与b做异或运算即:

 

0010001000101---àc

xor    1011010001110---àb

----------------------------------

      1001011001011---àd

 

注意到了吧,a == d  是成立的!那么我们可以得到一个结论:(a xor b) xor b = a。

同时我们还可以得到一个很诡异的swap操作:

a  ^=  b;  b ^= a; a ^= b;

自己拿起笔来模拟一下就很清楚的了。

 

2xor not (按位否)操作之间的关系

 

事实上很简单,nor操作是xor操作的一个特例。取反实质上就是同1做异或操作

~x =  x^0x FFFFFFFF

 

3、两个比较有趣的式子:(n ^(n+1))  ((n ^(n-1))+1)>>1

 

(1)首先来看(n ^(n+1))这个式子,假设n = 10011010, n+1 = 10011011,则:

 

10011010---àn

xor    10011011---àn+1

------------------------------------

      00000001---àans

 

如果还不能看出什么的话,再来一个例子:n = 11111111, n+1 = 100000000,则:

 

11110111---àn

xor     11111000---àn+1

-------------------------

      000001111---àans

 

得到的结果为n的倒数出现第一个0的位以及后面所有的1全部变成1,其它位都为0的数。

 

 

(2)再来看看((n ^(n-1))+1)>>1这个式子

假设n = 10011010, n-1 = 10011001,则:

 

10011010---àn

xor    10011001---àn-1

-----------------------------------------

      00000011---àans

ans+1 >> 1  = 000000100 >> 1 = 000000010

 

看出来了吧,也就是取出n出现倒数第一个1的位及该位后面的0组成的数

 

4、统计n1的奇偶性

 

思路:我们在按位与运算的时候学过了怎么计算一个整数中1的个数,但是我们现在用xor来解决吧:

x = x ^ (x>> 1);
x = x ^ (x>> 2);
x = x ^ (x>> 4);
x = x ^ (x>> 8);
x = x ^ (x>> 16);
return x& 1;

 

 

 

说道这里,顺便提一下怎么求解一个数n的前导0的个数,下面的代码来自Hacker's Delight


int nlz(unsigned x)
{
int n;
if (x ==  0return( 32);
   n =  1;
    if ((x >>  16) ==  0) {n = n + 16; x = x << 16;}
    if ((x >>  24) ==  0) {n = n +  8; x = x <<  8;}
    if ((x >>  28) ==  0) {n = n +  4; x = x <<  4;}
    if ((x >>  30) ==  0) {n = n +  2; x = x <<  2;}
   n = n - (x >>  31);
    return n;
} // 代码自己慢慢理解吧

 

<think>嗯,用户让我介绍一下几个位运算和逻辑运算符,包括它们的优先级和结合性。我需要先确认自己对这些概念的理解是否正确,然后组织语言用中文解释清楚。 首先,位异或XOR^运算符,优先级是从左到右。位或OR是|,也是从左到右。逻辑与AND是&&,逻辑或OR是||,它们的优先级可能不同,比如&&通常比||高。结合性都是左到右,所以运算时从左到右依次进行。 接下来,我需要分别解释每个运算符的作用和例子。比如,位异或用于两个二进制数的对应位比较,不同为1,相同为0。例如5^3的结果是6,因为二进制101和011异或后是110。位或则是任意一位为1结果位就是1,比如5|3得到7。 逻辑与和逻辑或用于布尔值,&&需要两边都为真才为真,||则是任意一边为真就为真。比如true && false是false,true || false是true。它们的短路特性也很重要,比如如果左边已经确定结果,右边就不会执行。 然后要提到优先级,位运算符的优先级通常高于逻辑运算符,但具体的顺序可能需要明确,比如&&比||优先级高,而位运算符中的^和|可能比逻辑运算符低?这点需要确认,比如在C语言中,优先级顺序是位运算中的&高于^,而^又高于|,然后才是逻辑运算符&&和||,其中&&高于||。不过用户这里可能只需要说明给出的几个运算符之间的相对优先级。例如,用户提到的顺序可能是指位异或和位或的优先级低于逻辑与和逻辑或?或者可能用户希望按照给出的顺序来排列优先级? 可能需要查阅运算符优先级表来确认。例如在常见的编程语言中,优先级顺序通常是:位运算中的&高于^^高于|,而逻辑运算中的&&高于||。不过用户给出的四个运算符中,位异或^、位或|、逻辑与&&、逻辑或||,正确的优先级顺序应该是从高到低:位异或^和位或|的优先级可能低于逻辑与&&和逻辑或||?或者是否位运算符的优先级通常高于逻辑运算符? 比如在C语言中,优先级顺序是:逻辑非! > 算术运算符 > 移位 > 关系运算符 > 位与& > 位异或^ > 位或| > 逻辑与&& > 逻辑或||。所以,位异或^和位或|的优先级高于逻辑与&&和逻辑或||。而用户的问题中提到的是,这些运算符的优先级,需要说明它们的顺序。 用户给出的四个运算符的顺序是:位异或XOR ^,位或OR |,逻辑与AND &&,逻辑或OR ||。但根据实际优先级,应该是位运算^和|的优先级高于逻辑运算符&&和||,而其中^的优先级高于|,而&&的优先级高于||。所以正确的优先级顺序应该是从高到低:^,|,&&,||。或者需要更准确的排列? 不过可能用户只是要介绍每个运算符的优先级和结合性,而不需要比较它们之间的相对优先级。比如,用户可能只是需要分别说明每个运算符的结合性都是左到右,以及它们的优先级顺序是怎样的。比如,在同一个表达式中,如果有多个运算符,它们的优先级如何排列。 例如,假设有一个表达式:a ^ b | c && d || e,根据优先级,应该先算^,再算|,然后&&,最后||。但根据实际C语言的优先级,顺序应该是&&高于||,而位运算的优先级高于逻辑运算。所以正确的顺序应该是先^,然后|,然后&&,最后||。例如,表达式会被解析为 ((a ^ b) | c) && d) || e。不过可能需要用括号来明确。 不过用户可能不需要这么深入,只是要介绍每个运算符的基本信息。所以应该分别说明每个运算符的作用、例子、优先级和结合性。 另外,用户可能对逻辑运算符的短路特性感兴趣,需要提及。例如,&&如果左边为假,右边不执行;||如果左边为真,右边不执行。 最后,可能需要总结运算符的优先级顺序,帮助用户理解在混合使用时如何计算。例如,位运算符的优先级高于逻辑运算符,而其中异或高于位或,逻辑与高于逻辑或。结合性都是左到右。 现在需要把这些内容组织成清晰的中文解释,分点说明每个运算符,并总结优先级顺序,可能给出例子说明运算顺序和结果。</think>以下是几个常用运算符的介绍,包括其功能、优先级及结合性: --- ### **1. 位异或 XOR `^`** - **功能**:对两个二进制数的每一位进行比较,**相同为0,不同为1**。 ```cpp 5 ^ 3 → 6 // 二进制 101 ^ 011 = 110(十进制6) ``` - **优先级**:高于逻辑运算符(如 `&&` 和 `||`),但低于算术运算符(如 `+`)。 - **结合性**:从左到右。 --- ### **2. 位或 OR `|`** - **功能**:对两个二进制数的每一位进行比较,**任意一位为1则结果为1**。 ```cpp 5 | 3 → 7 // 二进制 101 | 011 = 111(十进制7) ``` - **优先级**:低于 `^`,高于逻辑运算符。 - **结合性**:从左到右。 --- ### **3. 逻辑与 AND `&&`** - **功能**:判断两个布尔值是否同时为真(非零值)。若左操作数为假,则直接短路返回假。 ```cpp true && false → false ``` - **优先级**:高于 `||`,但低于位运算符(如 `^` 和 `|`)。 - **结合性**:从左到右。 --- ### **4. 逻辑或 OR `||`** - **功能**:判断两个布尔值是否至少有一个为真。若左操作数为真,则直接短路返回真。 ```cpp true || false → true ``` - **优先级**:最低(在列出的运算符中)。 - **结合性**:从左到右。 --- ### **优先级顺序总结(从高到低)** 1. 位异或 `^` 2. 位或 `|` 3. 逻辑与 `&&` 4. 逻辑或 `||` --- ### **结合性规则** 所有运算符均为**从左到右**结合,例如: - `a ^ b ^ c` 等价于 `(a ^ b) ^ c` - `a || b || c` 等价于 `(a || b) || c` --- ### **示例混合运算** ```cpp int result = a ^ b | c && d || e; // 等价于:((a ^ b) | c) && d) || e // 实际运算顺序: // 1. 先计算 a ^ b // 2. 结果再与 c 进行 | 运算 // 3. 结果再与 d 进行 && 运算 // 4. 最后与 e 进行 || 运算 ``` 若需明确运算顺序,建议使用括号 `()` 提高可读性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值