关于二进制序列的两道典型例题(位运算符)

来源:互联网 发布:win域名无法备案 编辑:程序博客网 时间:2024/06/06 20:25
1.求一个数的二进制序列中1的个数

一般方法:首先我们拿到一个十进制数,先得将它转化成二进制数(因为只需要求1的个数即可,因此不必管二进制序列的顺序,只需要求出1的个数即可),将十进制转化成二进制一般用除2取余的方法,而所得的余数即是二进制序列中的数,而通过计数器可以数出1的个数。

代码如下:

#include <stdio.h>int main(){int a;int count;printf("输入一个十进制数\n");scanf("%d",&a);        count=count_one_bits(a);printf("%d",count);return 0;}int  count_one_bits(int x){int y;int z;int count=0;while(x!=0){y=x%2;z=x/2;if(y==1)           count++;x=z;}return count;}

优化方案:

(1).上述方法中利用x%2,以及x/2,来完成除2取余法所需的步骤。而在C语言中x%2以及x/2可以理解成二进制数的一些操作。x%2是否等于1其实是取一个二进制数的最低位看它是否等于1,而x/2则是将二进制数右移1位,因此判断x%2是否等于1可以用位运算符进行操作【判断x&0x1是否等于1(因为&是只要有一个为0,结果就为0,举例:11110001&00000001=00000001而11110000&00000001=00000000)】,而x/2可以用x=x>>1或x>>=1代替。

代码如下:

#include <stdio.h>int main(){        printf("Please Enter: ");int x = 0;scanf("%d", &x);int old = x;int count = 0;        while (x != 0){if (x & 0x1){count++;}x >>= 1;        }      printf("%d one counts : %d\n", old, count);      return 0;}

(2).但是当一个数的二进制序列的最低的那个1的位数也很高的话,那么上述方法就显得不够好,每一位都得判断过去,太过于繁琐,因此我们可以通过一个小技巧来优化上述方案。x=x&(x-1),这个式子的结果是将x的二进制序列中的最低的那个1去掉。

代码如下:

#include <stdio.h>int main(){int x=0;int count=0;int old=0;printf("请输入1个十进制数\n");scanf("%d",&x);old=x;while(x!=0){x=x&(x-1);count++;}printf("%d one counts %d\n",old,count);return 0;}
*********************************************************************************************************************************************************************

2.获取一个数二进制序列中所有的偶数位和奇数位,分别输出二进制序列。

一般方法:将给定的数通过除二取余的方法,取出它的二进制序列中的每一位,并同时设定一个计数器count以记录每一位的位数,通过判断count是奇数还是偶数,将其对应的每一位放入2个不同的数组,而这两个数组即是奇数位与偶数位序列,当然这里的顺序是反的,因此在输出数组时要注意将数组中的元素按顺序倒着输出。

代码如下:

#include <stdio.h>int main(){int i=0;intj=0;int p,q;int a[16];int b[16];intx,z;int count=0;printf("请输入一个数:\n");scanf("%d",&x);while(0!=x){z=x%2;x=x/2;count++;if(0!=count%2){a[i]=z;i++;}else{b[j]=z;j++;}}printf("奇数位二进制序列:\n");for(p=i-1;p>=0;p--){printf("%d",a[p]);}printf("\n");printf("偶数位二进制序列:\n");for(q=j-1;q>=0;q--){printf("%d",b[q]);}printf("\n");return 0;}
优化方案:

(1).因为是对二进制序列进行操作的关系,我们可以先将一个数转换成二进制序列,并将它保存在一个数组当中,而将给定数转换成二进制我们除了用除二取余还可以通过位运算符进行操作(x&0x1==1保存1,x&0x1==0保存0【原理上面已经解释过】,还有每取了一次后要进行右移x=x>>1),但不管是除二取余还是位运算符每次取出的都是最低位,所以在保存到数组中的时候要倒着保存,然后对数组进行操作,依照角标分成奇数位与偶数位进行输出(这里需要注意的是数组角标是从0开始的,所以0,2,4,6,8.....是奇数位序列,1,35,7,9....是偶数位序列)。

代码如下:

#include <stdio.h>int main(){        int data = 0;int bits[32];int i = 0;printf("Please Enter: ");scanf("%d", &data);for (; i < 32; i++ ){if (data & 0x1){bits[i] = 1;}else{bits[i] = 0;}data >>= 1;}printf("偶数序列:");i = 31;for (; i >= 1; i-=2){printf("%d ", bits[i]);}printf("\n");printf("奇数序列:");i = 30;for (; i >= 0; i -= 2){printf("%d ", bits[i]);}printf("\n");        return 0;}
(2).上述方法是现将十进制转化成二进制,然后进行操作的,其实我们可以跳过这步直接对十进制进行操作,当然依旧是运用位运算符。

代码如下:

#include <stdio.h>int main(){        int data = 0;int i=0;printf("Please Enter: ");scanf("%d", &data);printf("偶数序列:");i = 31;for (; i >= 1; i-=2 ){if ( (data >> i) & 0x1 ){printf("1 ");}else{printf("0 ");}}printf("\n");printf("奇数序列:");i = 30;for (; i >= 0; i -= 2){if ((data >> i) & 0x1){printf("1 ");}else{printf("0 ");}}printf("\n");        return 0;}



0 0
原创粉丝点击