一.位操作符的分类
1.按位与:&
1.定义:
双方都是 1 ,才是一,否则返回 0 。
0 & 0 = 0 ;
0 & 1 = 0 ;
1 & 1 = 1 ;
2.用法:
1100 0101;
1111 0000;
1100 0000;
对于每一个二进制位,&1 则不变,&0 则变 0(即消除)。
2.按位或:|
1.定义:
只要有一个是 1 就为 1 ,两个都是 0 才是 0。
0 | 0 = 0 ;
0 | 1 = 1 ;
1 | 0 = 1 ;
1 | 1 = 1 ;
2.用法:
0100 1101 ;
1100 0110 ;
1100 1111 ;
对于每一个二进制位,|1 则置 1 ,|0 则不变。
3.按位异或:^
1.定义:
只要双方不同,就返回 1 ,反之则为 0 。
0 ^ 0 = 0 ;
0 ^ 1 = 1 ;
1 ^ 0 = 1 ;
1 ^ 1 = 1 ;
2.用法:
1100 0101 ;
0000 1111 ;
1100 1010 ;
对于一个数 ^0 ,保留原值。
4.按位左移:<<
对与每一个二进制位向左移位,右边空出的补 0 。
例:
0011 0101 ; (左移两位<<2)
1101 0100 ;
左移n位,相当于该数扩大2n倍。
5.按位右移:>>
(1)对与无符号位每一个二进制位向右移位,左边空出的补 0 ,称为逻辑右移。
例:
1010 1100 ; (右移两位>>2)
0010 1011 ;
(2)对与有符号位每一个二进制位向右移位,左边空出来的,正数补 0 ,负数补 1 ,
称为算数右移。
例:(省略成一个字节)
5 : 0000 0101 ; (右移两位>>2)
0000 0001 ………………………………………………(逻辑右移)
-7 :1000 0111 ;
1110 0001;………………………………………………(算数右移)
6.按位取反:~
即每一个二进制位取反即可。
0110 1010 ;(按位取反)
1001 0101 ;
二.位操作符的一些简单灵活运用
1.指定某一位为 1
0000 0000 0100 0001 ;(指定从第右4位为 1)
0000 0000 0000 0001 ;(将 1 左移3位)
0000 0000 0000 1000 ;
0000 0000 0100 0001 ;(和原数求或(|0 不变,|1 置 1 ))
0000 0000 0100 1000 ;
2.指定某一位为 0
0000 0000 0101 0001 ;(指定从第右5位为 0)
0000 0000 0000 0001 ;(将 1 左移4位)
~0000 0000 0001 0000 ;(在求反~)
1111 1111 1110 1111 ;
0000 0000 0101 0001 ;(和原数求与(&0 置 0,&1 不变 ))
0000 0000 0100 0001 ;
3.获取指定某一位的值
0000 1111 0011 1100 ;(指定获取第6位的值)
0000 0011 1100 1111 ;(右移5位>>5)
0000 0000 0000 0001 ;(与 1 求与)
0000 0000 0000 0001 ;(即可获得该位数)
4.判断奇偶数
如果一个数为奇数,则他的二进制数中的最后一位必定是 1 ,
则可以用该数&1,返回 0 就是偶数,反之。
5.判断一个数是否是 2 的指数
已知一个数如果是2的指数,则他的二进制数中只会有一个 1 。
而每次该数 x &(x-1)就会少一个最右边的 1 。
#include<stdio.h>
int main()
{
int n;
while (scanf("%d", &n) != EOF)
{
if ((n & (n - 1)) == 0)
printf("YES\n");
else
printf("NO\n");
}
return 0;
}
6.统计二进制数中的 1 的个数
每次该数 x &(x-1)就会少一个最右边的 1 。
直到全部为零。
#include<stdio.h>
int main()
{
int count = 0;
int n;
scanf("%d", &n);
while (n)
{
count++;
n = n & (n - 1);
}
printf("%d", count);
return 0;
}
7.统计二进制数中的 0 的个数
每次该数 x |(x-1)就会少一个最右边的 0 。
#include<stdio.h>
int main()
{
int count = 0;
int n;
scanf("%d", &n);
while (n+1)
{
count++;
n = n | (n + 1);
}
printf("%d", count);
return 0;
}