<pre class="objc" name="code">输出一个数的二进制序列中1的个数的讨论
#include<stdio.h>
int main()
{
int num = 0;
int count = 0;
scanf("%d", &num);
while (num)
{
if (num % 2 != 0)
{
count++;
}
num = num / 2;
}
printf("%d", count);
system("pause");
return 0;
}
以上这种方法只适用于正数,当输入一个负数时,会出现错误。(除法是对十进制数的整除,当除以负数时就无法实现)
要是能正确输出,可通过for循环的方法:负数在内存中是以反码的形式存储的,每循环一次,就将二进制数向右移一位,在VS编译器下是算数移位,即在高位补符号位(正数补0,负数补1),所以当使用负数时,向右移一位,高位补1,在使用while循环时,会出现死循环,即向右移位时,高位不断补1,循环无法跳出,所以使用for循环,整型为4个字节,2个比特位,循环32次)(左移和右移是对二进制序列的改变)
#include<stdio.h>
int main()
{
int num = 0;
int count = 0;
int i = 0;
scanf("%d", &num);
for (i = 0; i < 32; i++)
{
if (num % 2 != 0)
{
count++;
}
num = num >> 1;
}
num = num >> 1;
printf("%d", count);
system("pause");
return 0;
}
上面是将数定义为有符号数时的算法,当定义一个数为无符号数时,就不需要考虑正负数的区别:
#include<stdio.h>
int main()
{
unsigned int num = 0; //将整型数定义为无符号数
int count = 0;
scanf("%d", &num);
while (num)
{
if (num % 2 != 0)
{
count++;
}
num = num / 2;
}
printf("%d", count);
system("pause");
return 0;
}
<span style="color:#ff0000;">使用按位与的方法效率更高。思路是每次循环都去掉最低位的1,不需要像上面的方法一位一位的比较</span>
#include<stdio.h>
int main()
{
int number = -1;
int count = 0;
while (number)
{
count++;
number = number&(number - 1);
}
printf("%d", count);
system("pause");
return 0;
}
<span style="color:#ff0000;">根据按位与的方法可以扩展:判断一个数是否是2的次方数</span>,
<pre class="objc" name="code">#include<stdio.h>
int main()
{
int number = 16;
if ((number&(number - 1)) == 0); 即这个数与比他小1的那个数相与,为零,则是2的次方数。
printf("%d是2的次方数", number);
system("pause");
return 0;
}
</pre><pre class="objc" name="code">