【位运算进阶之----异或(^)】
因此,可以使用异或操作来判断两个数的奇偶性。通过对数组中的所有元素进行异或操作,如果结果为0,则表示数组中没有落单的元素;例如,假设有两个命题p和q,它们的真假分别为(p =1,q = 0) 或(p=0,q=1)。通过将明文和密钥进行异或操作得到密文,再将密文和密钥进行异或操作得到明文。当然,还有很多交换变量值的方法,我们这里就不展开论述了,以后有机会会进行讲解。即一个数与自身进行异或操作的结果为
今天我们来学习C语言中的异或。
文章目录
一、基本知识:
✨在C语言中,异或(XOR)是一种逻辑运算符,用符号^
表示。异或操作是将两个操作数的每一位
进行比较,如果相同
则结果为0
,如果不同
则结果为1
。
左操作数 | 右操作数 | 结果 |
---|---|---|
0 | 0 | 0 |
0 | 1 | 1 |
1 | 0 | 1 |
1 | 1 | 0 |
- 例如,假设有两整数变量a和b,其二进制表示分别为:
a = 1010 , b = 1100 - 执行a ^ b操作后,得到的结果是:
a ^ b = 0110
✨总结起来,0和任何数异或还是任何数
,1和任何数异或则是任何数的取反
。
异或操作满足的定律:(important)
-
结合律:对于任意三个操作数a、b、c,有
(a ^ b) ^ c = a ^ (b ^ c)
。即异或操作在多个操作数之间满足结合律。 -
交换律:对于任意两个操作数a和b,有
a ^ b = b ^ a
。即异或操作的顺序可以交换。 -
自反性:对于任意操作数a,有
a ^ a = 0
。即一个数与自身进行异或操作的结果为0。 -
零元素:对于任意操作数a,有
a ^ 0 = a
。即一个数与0进行异或操作的结果为它本身。 -
唯一性:对于任意操作数a,有
a ^ a = 0
,a ^ 0 = a
。即一个数与自身进行异或操作的结果为0,与0进行异或操作的结果为它本身。
二、拓展应用:
1. 交换两个变量的值:
✨可以使用异或操作来交换两个变量的值,而无需使用第三个变量。
例如:
int a = 10;
int b = 20;
a = a ^ b;
b = a ^ b;
a = a ^ b;
// 现在a的值为20,b的值为10
❓可能会有人有疑问,为啥右边都是a^b,但最终的结果就可以交换呢?让我们来一步步分析:
- 首先,通过
a = a ^ b
后,a的值将会发生改变,至于变为多少,我们不关心,因为没必要算(实在想算也可以,写出二进制表达后再用定义计算)。 - 然后,通过
b = a ^ b
后,因为a的值已经发生了改变,即此式等价于b = a ^ b ^ b = a ^ 0 = a
,从而将a的值赋给了b。 - 最后,
a = a ^ b = a ^ b ^ a = a ^ a ^ b = 0 ^ b = b
。从而实现两个数值的交换。
✨你是否又想到了排序算法中两个值的交换呢?当时我们是通过定义一个临时变量(中间媒介)来完成两个数的交换,类似下面这种方法:
int temp=a;
a=b;
b=temp;
当然,还有很多交换变量值的方法,我们这里就不展开论述了,以后有机会会进行讲解。
2. 判断两个数的奇偶性:
✨可以使用异或操作来判断两个数的奇偶性。如果一个数的二进制表示的最后一位为1,则该数为奇数;如果最后一位为0,则该数为偶数(我们上节已经讲过了)。因此,可以使用异或操作来判断两个数的奇偶性。例如:
int num = 10;
int result=num ^ 1
if (result<num) {
printf("num是奇数");
} else {
printf("num是偶数");
}
为啥要这样写呢❓
- 如果一个数为奇数,则其的二进制表示的最后一位为1,和1异或后,最后一位变为0,其余位值不变,所以异或的结果小于原数;(小了1)
- 反之,若一个数为偶数,则其的二进制表示的最后一位为0,和1异或后,最后一位变为1,其余位值不变,所以异或的结果大于原数;(大了1)
3. 检测落单的数(出现奇数次的数):
✨异或操作可以用来检测数组中是否存在落单的元素。通过对数组中的所有元素进行异或操作,如果结果为0,则表示数组中没有落单的元素;反之则有,且计算结果就是该落单的数。例如:
int arr[] = {1, 2, 1, 3, 4, 3, 2, 1, 1};
int n = sizeof(arr) / sizeof(arr[0]);
int result = 0;
for (int i = 0; i < n; i++) {
result = result ^ arr[i];
}
if (result == 0) {
printf("数组中没有落单的元素");
} else {
printf("数组中存在落单的元素,输出如下:");
printf("%d",result);
}
检测丢失的数:
- 给定范围[a,b]的一系列数,但是一个调皮的数跑丢了,需要你把它找出来,请问该怎么找?
- 答:利用今天学习的异或知识就能轻松解决,即把[a,b]所有的数(b-a+1个)和丢失一个数的那些数(b-a个)放在一堆,然后一起异或,重复的数必定两两相消,剩下的一个数就是那个调皮的数。
4. 加密和解密:
✨异或操作可以用来进行简单的加密和解密操作。通过将明文和密钥进行异或操作得到密文,再将密文和密钥进行异或操作得到明文。例如:
char plaintext[] = "Hello World";
char key = 'A';
int n = strlen(plaintext);
for (int i = 0; i < n; i++) {
plaintext[i] = plaintext[i] ^ key;
}
printf("加密后的密文:%s\n", plaintext);
for (int i = 0; i < n; i++) {
plaintext[i] = plaintext[i] ^ key;
}
printf("解密后的明文:%s\n", plaintext);
😄哈哈,是不是很有趣呢?
三、与离散数学中的异或进行对比:
✨离散数学中的异或运算是一种基于布尔代数的运算,也称为逻辑异或运算
。它的规则与C语言中的异或运算类似,只不过它的操作对象是逻辑值
(真或假)。
- 在离散数学中,异或运算的结果为真(1)的条件是:有且仅有一个操作数为1。如果两个操作数都为1或都为0,则结果为假(0)。
例如,假设有两个命题p和q,它们的真假分别为(p =1,q = 0) 或(p=0,q=1)。那么p ⊕ q的结果为1,因为有且仅有一个操作数为1。
————————————————
好了,今天的讲解就到这里了,相信你也是收获满满吧!❤️
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)