对于一个数字n,想要在其二进制形式中删去一个1,具体的实现方式是令n=n&(n-1)。
在二进制数中去掉一个1,这种操作的意义可以体现在很多方面,比如说我想统计一个二进制数中到底有几个1,那我i就可以反复用这个操作处理这个数,每次处理后都将处理次数加1,这样,当该数中的所有1都被删去时,这个数的值就变成0,我可以设定判断条件,while(n!=0)或直接while(n),以跳出循环。这时,打印出记录循环次数的那个整型变量就得到了该二进制数中1的个数。
分析:对于任意一个二进制数n,当n-1时,整个二进制数中的最后一个1势必会变成0(其他位的变化不管,只考虑原先n中的最后一个1)。首先分析n,那个发生改变的“最后一个1”后面全都是0(很好理解,因为它是最后一个1,那它后面肯定都是0),然后分析n-1,对于n-1而言,相比于n,发生变化的“最后一个1”前面的数字不变(可以这样理解,越往前的数字越大,想要改变这些数字也就越难,需要对数字进行更大程度的变化),其它部分,“发生变化的那个1”变成了0,后面的部分不需要考虑(实际上是全变成了1,为什么不需要考虑后面会提到)。这时,清楚了两个数字的结构之后,将两个二进制数按位与(全都是1时才为1,否则为0),根据按位与的特点,我已经知道了在n中,"发生变化的1“的后面全都是0,那n-1中,那一位后面是0是1我也就不需要考虑了。
如图所示, 经过操作之后,n&(n-1)相比于n就少了一个1。
具体应用如下:该程序就是找到一个数字的二进制形式中有几个1。
#include<stdio.h>
int numberof1(int n)
{
int count = 0;
int i = 0;
while (n)
{
n = n & (n - 1);
count++;
}
return count;
}
int main()
{
int n = 0;
printf("请输入一个数:");
scanf("%d",&n);
int ret = numberof1(n);
printf("%d\n", ret);
return 0;
}