这是一个关于位运算的文章,在学习过程中发现位运算的作用很奇妙,有些不容易观察出来的东西,利用位运算却能很轻松的解决
**
1. 求出一个十进制数的二进制形式中1的个数
**
思路:原理就是利用 & 运算时1 & 1为真其余为假的大原理。
每检测一次让这个数往右移动一位,然后与1做 & 运算,如果是1则说明这个数的这个位上面是1,则将计数器加1,否则继续循环直到这个数右移变为0.代码实现如
#include <stdio.h>
int main()
{
int n = 0, num = 0, t = 0;
printf("请输入一个数字,然后会输出它的二进制里有几个1\nn = ");
scanf("%d",&n);
t = n;
while(n != 0)
{
if(n & 1 == 1)
num++;
n= n>>1;
}
printf("%d里面有%d个1\n",t,num);
return 0;
}
2.从已知范围的数里找出唯一一个出现两次的数。
例:有1001个数范围是0-999只有一个数出现两次其他数均只出现了一次。求出这个数。
思路:
位运算的异或运算可以消去一堆数里面出现偶次的数。即x ^ a ^ a = x.
又因为已知数的范围,所以可将该题演变为将该范围的所有数出现为偶次,而目标数字出现了奇数次。即先用一个为0的变量x与0-999的所有数字进行异或操作。这步就是先保证将所有数字出现一次。
再将这所有的数字与x进行异或操作。这下就可以消除出现一次的数并保留下出现两次的数了。
(找出落单的数直接异或操作输出即可)
代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void show(int a[], int N);
int main()
{
int N = 11, x = 0, number = 0;
int *a;
a = (int *)calloc(N,sizeof(int));
int i = 0;
for(i = 0; i<N-1; i++)
a[i] = i+1;
srand(time(NULL));
//show(a,N);
number = rand() % (N-1)+1;
a[N-1] = number;
show(a,N);
x= 0;
for(i = 1; i <= N-1; i++)
x = x^i;
for(i = 0; i< N; i++)
x = x^a[i];
printf("%d\n",x);
return 0;
}
void show(int a[], int N)
{
int i = 0;
for(i = 0; i < N; i++)
printf("%d%c",a[i],i == N-1?'\n':' ');
}
3.判断一个数是不是2的整数次幂
思路:写出2的整数次幂可以发现,2的整数次幂都是在最高位为1,其余为0.
再写出它的后一位。
比如8和7
8的二进制是1000
7的二进制是0111.
再比如16和15
16的二进制是10000
15的二进制是01111
可以发现2的整数次幂的数和它减一的数做&运算的话,结果始终为0.
则可以利用此特点找出二的整数次幂,代码实现如下。
//以0为测试结束的标志
#include <stdio.h>
int main()
{
int n = 0;
printf("请输入一个数,然后会输出它是不是2的整数次幂\nn
= ");
while(scanf("%d",&n)!=EOF)
{
if(n == 0)
break;
if((n & (n-1) )== 0)
printf("YES\n");
else
printf("NO\n");
printf("请输入一个数,然后会输出它是不是2的整数次幂\nn
= ");
}
return 0;
}
4.将整数的奇偶位互换
思路:还是利用 & 运算,因为int数据类型的数只有32位,
所以只要
利用一个所有偶数位上为1而奇数位为0的数和该数做 & 运算就可以取得偶数位上的数,同样奇数位只需要一个所有奇数位上为1而偶数位为0的数和该数做 & 运算就可以取得这个数的奇数位。
最后再把偶数右移一位,奇数左移一位即可。
代码实现如下
#include <stdio.h>
int main()
{
int i = 0,a=0;
int ou=0,ji=0;
printf("请输入一个数将输出它的奇数位和偶数位调换前后的数\ni = ");
scanf("%d",&i);
ou = i&0xaaaaaaaa;
ji = i&0x55555555;
a = ou ^ ji;
printf("奇偶转换之前 = %d\n",a);
a = (ou>>1)^(ji<<1);
printf("奇偶转换过后 = %d\n",a);
}
5.乘二挪整,二进制表示浮点整数。
代码实现如下
#include <stdio.h>
#define max 34
int main()
{
double n = 0, t = 0;
int i = 0, num = 0;
int a[max]= {0};
printf("请输入一个实数\nn = ");
scanf("%lf",&n);
t = n;
//乘二挪整
while( t )
{
t*=2;
if(t >= 1)
{
a[i] = 1;
t -= 1;
}
else
a[i] = 0;
i++;
}
num = i-1;
//printf("num = %d\n",num);
if(num > 32)
printf("ERROR\n");
else
{
printf("0.");
for(i = 0; i <= num; i++)
printf("%d",a[i]);
}
return 0;
}