题目:输入一个整数,输出该数二进制表示中1的个数。
// 二进制中1的个数 #include <stdio.h> int wrong_count_1_bits(int n) // 错误解法: 当n为负数时, n>>=1右移, 最高位补1, 陷入死循环 { int count = 0; while(n) { if( n & 1 ) ++count; n >>= 1; } return count; } int count_1_bits(int n) // 常规解法, 若sizeof(int)=4, 循环32次 { unsigned int mask = 1; int count = 0; while(mask) // 循环32次后, mask变为0 { if( mask & n ) ++count; mask <<= 1; } return count; } int perfect_count_1_bits(int n) // 高效解法, 若n含二进制位为1的位数为t, 则循环t次 { int count = 0; while(n) { n = (n-1) & n; // 执行该语句后, n的二进制表示中, 最右边的1被置为0, 其余各位不变, 也即是每循环一次, 消去n最靠右的1 ++count; } return count; } int static_table_count_1_bits(int n) // 静态表法 { int table[16] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 }; int count =0 ; while (n) { count += table[n &0xf] ; n >>=4 ; } return count ; } int main(void) { printf("sizeof(int)=%d ",sizeof(int)); printf("%d ",0x0fffff73); // 非负数正常; 负数(如0xffffff73)会导致程序在wrong_count_1_bits函数处陷入死循环 int count1 = count_1_bits(0x0fffff73); int count2 = perfect_count_1_bits(0x0fffff73); int count3 = wrong_count_1_bits(0x0fffff73); int count4 = static_table_count_1_bits(0x0fffff73); printf("count1=%d,count2=%d,count3=%d,count4=%d ",count1,count2,count3,count4); return 0; }
关键点:把一个整数减去1之后再和原来的整数做按位与运算& ,得到的结果相当于把整数的二进制表示中的最右边一个1变成0。
相关题目1:用一条语句判断一个整数是不是2的整数次方
if( (n-1)&n == 0 ) printf("Yes ");
相关题目2:输入两个整数m和n,计算需要改变m的二进制表示中的多少位才能得到n。
步骤1:求这两个数的异或 t = m^n;
步骤2:统计异或结果t的二进制表示中1的个数,即为需要改变的位数。
相关题目3:二进制中0的个数
方法1:上面常规解法中,改成 if( n^mask == 1 ) ++count;
方法2:先使用上面某种方法求得“二进制中1的个数”,间接求解:sizeof(int)*8 - 1的个数