前言:
本篇文章致力于通过例题讲解帮助读者理解操作符的使用。
阅读须知:
1. ‘ & ’按位与,两个1取1,其余为0。
2.‘ | ’按位或,两个0取0,其余为1。
3. ‘ ^ ’按位异或,相异取1。
4.‘ ~ ’按位取反。
5.n^n=0,n^0=n。
6.(n>>i)&1可以求二进制最右边的数。
注意:在计算机中我们针对的改变是补码的,但计算机打印在屏幕上的是转化后的原码,不要搞错了。
目录:
方法二:
(一)交换两个变量(不创建临时变量)
1.题目要求
不允许创建临时变量,交换两个整数的内容
2.代码演示
#include<stdio.h>
int main()
{
int a = 1;
int b = 2;
a = a ^ b;
b = a ^ b;
a = a ^ b;
printf("a=%d,b=%d\n", a, b);
return 0;
}
3.代码解析
‘ ^ ’按位异或的特点是:相异取一。两个相同的数,它们二进制的每一位都相同,所以每一位都取0,所以有n^n=0。两个不同的数,一个数是0,取相异的位为1,其余为0,于是有n^0=n。
(二)统计二进制中1的个数
1.题目要求
写一个函数返回参数二进制中 1 的个数。(题源:牛客网)
比如: 15 0000 1111 4 个 1
2.思路分析
方法一:
我们可以类比十进制求1 的个数的方法:
所以我们可以通过不断地除2和%2得到15的二进制数,再去找1
由此我们得到关键步骤:
while (num)//当num等于0时,条件为假,跳出循环
//且0的补码中全是0
{
if (num % 2 == 1)
{count++;}
num = num / 2;
}
注意:我们假设当num=-2时,就有(-2)%2 == 0,无法进行count ++ ,但是我们知道负数的符号位始终为1,应当进行count++操作,所以为了避免这种情况发生,我们要在while循环前声明:unsigned int num!!!
方法二:
我们这里也可以用按位与‘&’来做,我们想知道二进制最低位是否为1时用&。
我们可以通过这个方法来找1,我们不只要判断最低位,还要判断其他位是否为1,所以我们可以通过让n的补码不断地>>1(右移1位),这一步可以通过for循环来完成。
注意:(n>>i)里的n值不变,改变的是括号这个整体的值。
for(i=0;i<32;i++)
{
if((n>>i)&1==1)
//n不断地右移,把每一个数逐一放在最低位,然后左边不断补0
//如果括号内的表达式可以运行就count++
{count++};
}
这里给大家推一遍过程:
方法三:
还有一种很少见的方法,为大家简单做个介绍:n=n&(n-1)
由此我们可以得到思路,利用while循环判断n是否是非0,若为真,执行一次n=n&(n-1)
,再去掉一个1,每执行一次就count++,直到n=0,二进制中没有1了为止。
3.代码演示
代码1:
#include<stdio.h>
int main()
{
unsigned int num;
int count = 0;
printf("请输入一个整数:");
scanf_s("%d", &num);
while (num)//当num等于0时,条件为假,跳出循环
//且0的补码中全是0
{
if (num % 2 == 1)
{count++;}
num = num / 2;
}
printf("其二进制数共有%d个1。", count);
return 0;
}
代码2:
{
int count = 0;
int n,i;
printf("请输入一个整数:");
scanf_s("%d", &n);
for (i = 0; i < 32; i++)
{
if((n>>i)&1==1)//(n>>i)并没有改变n的值,而是改变了它们运算的结果
{
count++;
}
}
printf("其二进制数共有%d个1",count);
return 0;
}
代码3:
#include<stdio.h>
int main()
{
int n;
int count = 0;
scanf_s("%d", &n);
while (n)
{
n = n & (n - 1);
count++;
}
printf("共有%d个1",count);
return 0;
}
(三)求两个数二进制中不同位的个数
1.题目要求
编程实现:两个int(32位)整数m和n的二进制表达中,有多少个位(bit)不同?(题源:牛客网)
输入例子:
1999 2299
输出例子:7
2.思路分析
我们设想一下,我们知道一个数的补码一共有32位,如果我输入的两个整数一个是3,一个是5:
我们要查找这两个数的补码中有几个位不一样,我们可以利用按位异或的特点:不一样的位取1,其余为0。由此得到一个新的二进制数:
我们由第二个大题第二个方法可知,我们可以通过这个代码查找出有几个1,这样就知道二进制不同位的个数了。
for(i=0;i<32;i++)
{
if((n>>i)&1==1)
//n不断地右移,把每一个数逐一放在最低位,然后左边不断补0
//如果括号内的表达式可以运行就count++
{count++};
}
3.代码演示
#include <stdio.h>
int main()
{
int a, b;
int count = 0;
scanf("%d %d", &a, &b);
int c = a ^ b;
for (int i = 0; i < 32; i++)
{
if(((c >> i) & 1) == 1)
{
count++;
}
}
printf("%d", count);
return 0;
}
(四)二进制位置1或0
1.题目要求
比如:将13的二进制序列的第五为修改为1,然后再改回0。
2.思路分析
3.代码演示
代码1:
#include<stdio.h>
int main()
{
int n;
printf("请输入一个整数:");
scanf_s("%d", &n);
n |= (1 << 4);
printf("%d\t", n);
n &=(~(1 << 4));
printf("%d", n);
return 0;
}
代码2:
#include<stdio.h>
int main()
{
int n;
printf("请输入一个整数:");
scanf_s("%d", &n);
n |= (1 << 4);
printf("%d\t", n);
n ^=(1 << 4);
printf("%d", n);
return 0;
}
结果:
(五)单身狗1
1.题目要求
在一个整型数组中,只有一个数字出现一次,其他数组都是成对出现的,请找出那个只出现一次的数字。
例如:
数组中有:1 2 3 4 5 1 2 3 4,只有5出现一次,其他数字都出现2次,找出5
2.思路分析
跟据第一题,我们知道n^n=0,n^0=n。而题目中的数组里只有一个数出现了一次,所以我们如果让它们每一个数都相异或:
由此就可以得到我们的单身狗了。
3.代码演示
#include<stdio.h>
int Alone(int arr[], int n)
{
int i;
int result = 0;
for (i = 0; i < n; i++)
{
result ^= arr[i];//和阶乘的写法类似
}
return result;
}
int main()
{
int alone;
int result = 0;
int arr[] = {1,2,3,4,5,1,2,3,4};
int n = sizeof(arr) / sizeof(arr[0]);//求数组的个数
//注意数组名不要写错了
alone = Alone(arr, n);//注意这里arr没有【】!
printf("单身狗是%d", alone);
return 0;
}
(六)打印整数二进制的奇数位和偶数位
1.题目要求
获取一个整数二进制序列中所有的偶数位和奇数位,分别打印出二进制序列
2.思路分析
第一步:我们首先假设最低位是第31个,最高位是第0个。然后再用for循环,每循环一次就让i减一个2,分别求二进制的奇数位和偶数位。
第二步:二进制中只由0和1组成,我们可以通过让二进制数经过这个代码:(num>>i)&1(第二个答题第二个方法)求出每循环一次后的最低位是多少,再printf打印出来。
3.代码演示
#include<stdio.h>
void Printbit(int num)
//不需要返回值,直接打印即可,所以在函数前加个void
{
printf("偶数位:");
for (int i = 31; i >= 1; i -= 2)
//个数从0开始计数,所以这里的第一个数是偶数位
{
printf("%d ", (num >> i) & 1);//把最低位的数字求出来
}
printf("\n");
printf("奇数位:");
for (int i = 30; i >= 0; i -= 2)
{
printf("%d ", (num >> i) & 1);
}
printf("\n");
}
int main()
{
int num;
printf("请输入一个整数:");
scanf_s("%d", &num);
Printbit(num);
return 0;
}
好了今天就先分享这么多,有问题的朋友请再评论区留言,我会回复的。如果你喜欢本篇文章的内容可以为我点个赞吗?非常感谢^ ^