位操作符以及几种常见应用
Posted 张同学吧
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了位操作符以及几种常见应用相关的知识,希望对你有一定的参考价值。
操作符详解
原反补
加法器计算机里面,只有加法器,没有减法器,所有的减法运算,都必须用加法进行。通过被减数的补码代替被减数,可以把减法转变为加法运算。
补码减法所依据的基本关系式:
[x-y]补 =[x+(-y)]补= [x]补+ [-y]补
原码:1000 0001
反码:1111 1110 原码取反
补码:1111 1111 反码+1/原码从右数第一个1保留,其余位取反,符号位不变
负数的原反补才有意义,正数的原反补均相同。
数0的补码表示是唯一的:
[+0]补=[+0]反=[+0]原=00000000
[ -0]补=11111111+1=00000000
移位操作符
<< 左移操作符
>> 右移操作符
1、左移操作符
规则:左边扔掉,右边补0;
2、右移操作符
1、逻辑移位规则:右边丢掉,左边用0补充
2、算术移位规则:右边扔掉,左边补符号位
3、示例
1)负数的右移:负数右移的二进制的右边补1。如果一直右移的话,最后就就变成0xFFFFFFFF 即-1。如: -4>>1 为-2 ;-4>>2为-1;-1>>-1
2)负数的左移:跟正整数左移一样,右边补0,一直左移的话,最后就是0。
3)正数的右移:相当于除以2。
4)正数的左移:相当于乘以2。
int main() {
int a = -1;
int b = 2;
printf("-1左移一位后:%d\\n",a << 1);//1111 1111左移一位之后变为1111 1110=-2;
printf("-1右移一位后:%d\\n",a >> 1);//仍然是-1;
printf("2左移一位后:%d\\n",b << 1);//0010左移一位之后变为0100=4;
printf("2右移一位后:%d\\n",b>> 1);//0010右移一位之后变为0001=1;
return 0;
}
位操作符
& :按位与
| :按位或
^ :按位异或
注:他们的操作数必须是整数
例1:不创建临时变量,交换两个数
第一种
#include <stdio.h>
int main()
{
int a = 10;
int b = 20;
a = a^b;
b = a^b;
a = a^b;
///
a=a+b;//第二种方式
b=a-b;
a=a-b;// 不用担心溢出,因为溢出之后会被减回来。
printf("a = %d b = %d\\n", a, b);
return 0;
}
提一下为什么不用担心溢出,因为在计算机的数据的存储中好比是一个圆:以int型为例。int的存储范围是(-2147483648,2147483647),所以我们可以看成一这样可以循环的圆,2147483647+再加上一个1就会变成-2147483648
#include<stdio.h>
int main() {
int a = 2147483647;
printf("%d\\n", a + 1);
int b = -2147483647-1;//注意不能直接取值到-2147483648,会报错
printf("%d\\n", b - 1);
return 0;
}
不明白的小伙伴可以自己动手算一算
例2:求一个整数存储在内存中二进制中1的个数
//方法1
#include <stdio.h>
int main()
{
int num = 10;
int count= 0;//计数
while(num)//缺陷:如果num为负数会死循环
{
if(num%2 == 1)//每一次都模2,相当于取了二进制的最后一位,如果为1则记录一次
count++;
num = num/2;//num右移一位
}
printf("二进制中1的个数 = %d\\n", count);
return 0;
}
//方法2:
#include <stdio.h>
int main()
{
int num = -1;
int i = 0;
int count = 0;//计数
for(i=0; i<32; i++)//负数也可以计算,因为不管正负循环都只循环32次,不会再记录后补的位
{
if(((num>>1) & 1) != 0)
{
count++;
}
}
printf("二进制中1的个数 = %d\\n",count);
return 0;
}
//但是这里必须循环32次,还可以对循环的次数进行优化
//方法3,最终版本,但也是最难想到的版本
#include <stdio.h>
int main()
{
int num = -1;
int i = 0;
int count = 0;//计数
while(num)//num不等于0时
{
count++;
num = num&(num-1);//每&一次都会减少一个1,所以记录循环次数就可以得到1的位数
}
printf("二进制中1的个数 = %d\\n",count);
return 0;
}
百度笔试题:如何判断一个数字是否为2的K次幂(不需要计算K)
通过题干分析我们知道,如果是2的K次幂,那么二进制数中只有1个1,所以我们就判断count最终是不是等于1,就可以了
#include <stdio.h>
int main()
{
int num = 0;
scanf("%d", &num);
int i = 0;
int count = 0;//计数
while (num)//num不等于0时
{
count++;
num = num & (num - 1);//每&一次都会减少一个1,所以记录循环次数就可以得到1的位数
}
if (count == 1)
{
printf("该数字是2的K次幂");
}
else {
printf("该数字不是2的K次幂");
}
return 0;
}
以上是关于位操作符以及几种常见应用的主要内容,如果未能解决你的问题,请参考以下文章
一张图,理顺 Spring Boot应用在启动阶段执行代码的几种方式