一、选择题
1、下面哪个是位操作符:( )
A.&
B.&&
C.||
D.!
答案解析:
答案:A
A正确,&——按(二进制)位与,对应的二进制位:有0则0,两个同时为1才为1。
B、C错误,&&与||——逻辑操作符
D错误,!——单目操作符
知识点:
1、位操作符:
(1)运算规则:
①&——按(2进制)位与,对应的二进制位:有0则0,两个同时为1才为1
②|——按(2进制)位或,对应的二进制位:有1则1,两个同时为0才为0
③^——按(2进制)位异或,对应的二进制位:相同为0,相异为1
(2)注意:
①他们的操作数必须是整数
②是针对二进制位进行运算的
2、逻辑操作符
(1)运算规则
①&&——逻辑与(并且:参与运算的两个逻辑值都为真时,结果为真)
②||——逻辑或(或者:参与运算的两个逻辑值都为假时,结果为假)
(2)逻辑操作符的短路特性
①&&操作符,左边为假,右边无需计算
②||操作符,左边为真,右边无需计算
(3)注意区分逻辑与(或)和按位与(或)
①逻辑与(或)----->只关注真假
②按位与(或)----->通过二进制计算得到
二、编程题
1、交换两个变量(不创建临时变量)
不允许创建临时变量,交换两个整数的内容
方法1:计算得到
方法2:使用按位异或操作符
知识点:
1、按位异或操作符
(1)运算规则:^——按(二进制)位异或,对应的二进制位:相同为0,相异为1
(2)性质:
①a^a=0
②0^a=a
③异或支持交换律:a^a^b=a^b^a
(3)异或操作符交换两个变量的局限性
①可读性差
②效率也不如使用临时变量的方法
③异或只针对整数的交换
代码1:计算得到
#include<stdio.h>
int main()
{
int a = 0;
int b = 0;
//输入a,b
scanf("%d %d", &a, &b);
//打印交换前a,b
printf("交换前:a=%d b=%d\n", a, b);
//交换a,b
a = a + b;
b = a - b;
a = a - b;
//打印交换后a,b
printf("交换后:a=%d b=%d\n", a, b);
return 0;
}
代码2:使用按位异或
#include<stdio.h>
int main()
{
int a = 0;
int b = 0;
//输入a,b
scanf("%d %d", &a, &b);
//输出交换前a,b
printf("交换前:a=%d b=%d\n", a, b);
//交换a,b
a = a ^ b;
b = a ^ b;
a = a ^ b;
//输出交换后a,b
printf("交换后:a=%d b=%d\n", a, b);
return 0;
}
2、统计二进制中1的个数
二进制中1的个数__牛客网
1、在网上平台答编程题(如牛客网),有两类:
①IO型:从main函数开始写,要写输入、计算、输出等
②接口型:不需要写主函数,默认主函数就是存在的(后台存在),你只需要完成函数就可以了。
本题就是一道接口型。
我们平时练习可以在自己的编译器,先实现再复制粘贴到答题平台上验证。
代码1:
我们是怎么得到10进制整数的每一位的?
类比:
这种方法虽然也能求出2进制中1的个数,但是我们把题目给的形参改变了,所以不符合题意。排除掉。
#include<stdio.h>
int NumberOf1(unsigned int n)
{
int count = 0;//计数器,统计1的个数
//循环%2 /2,直到n等于0
while (n)
{
if (n % 2 == 1)
{
count++;
}//如果是1,统计
n /= 2;//循环调整部分
}
return count;
}
int main()
{
int n = 0;
//输入
scanf("%d", &n);
//计算--调用函数
int ret = NumberOf1(n);
//输出
printf("%d\n", ret);
return 0;
}
代码2:
我们写的这个代码没有修改题目函数的返回类型、函数名、形参所以粘贴复制到牛客网是成功的。
知识点:
1、>>右移操作符
移位规则:
①(常见如VS)算术右移:左边补原来的符号位,右边抛弃
②逻辑右移:左边直接补0,右边抛弃
2、&——按位与
移位规则:对应的二进制位:有0则0,两个同时为1才为1
3、总结:我们判断一个数的每一位的数时,通常从低位入手
4、n虽然发生了右移,但是实际上n在没有被赋值的情况下,自身的值不会发生变化(即n>>i的结果是移位之后的效果,但是n是不变的)
#include<stdio.h>
int NumberOf1(int n)
{
int count = 0;//计数器,统计1的个数
int i = 0;//循环变量
//循环32次,每次右移i
for (i = 0; i < 32; i++)
{
if ((n >> i) & 1)
{
count++;
}
}
return count;
}
int main()
{
int n = 0;
//输入
scanf("%d", &n);
//计算--调用函数
int ret = NumberOf1(n);
//输出
printf("%d\n", ret);
return 0;
}
代码3:
但是还有效率更高的解法:
我们粘贴函数部分上牛客验证:
#include<stdio.h>
int NumberOf1(int n)
{
int count = 0;//计数器,统计1的个数
while (n)
{
n = n & (n - 1);
count++;
}
return count;
}
int main()
{
int n = 0;
//输入
scanf("%d", &n);
//计算--调用函数
int ret = NumberOf1(n);
//输出
printf("%d\n", ret);
return 0;
}