引:中国某杀毒软件公司2010年3月笔试题
#include <iostream> using namespace std; int func(int n) { int nCount = 0; while( n ) { nCount++; n = n & (n-1); } return nCount; } int main(int argc, char *argv[]) { cout << func( 9999 ) << endl; return 0; }
输出结果是多少?
答案是:8
一开始看题目我是没做出来的,因为自己对类似于位操作不是很熟悉,所以即使知道这个是求含1的个数,但是依然没想通。
怎么 n = n & (n-1) 就可以求得1的个数呢。
后来分析下,有了些许的明白。
解释可以如下:
比如对于某二进制数 n=1xxx...100
那么n-1=1xxx...011
那么n & (n-1) = 1xx...000
这样的话,每进行一次n&(n-1)运算,那么n的末尾1都会消除掉,这样的话每一次都会消掉一个1,到最后n就为0了,如此就可以知道n含有多少个1了。
附:
某面试题要求用一个表达式来判断一个整数是否为2的n次方,实质上,我们只要判断该整数含1的个数是否为0即可。所以表达式可表示为:
!(n & (n-1) )
如果为真那么就说明是。
#include <stdio.h> int GetOneCountsByDiv( int x )/*除法*/ { int n=0; while( x ) { if( x%2 ) n++; x /=2 ; } return n; } int GetOneCountsByMoveR( int x )/*右移位操作*/ { int n=0; while( x ) { if( x&1 ) n++; x = x>>1; } return n; } int GetOneCountsByAnd( int x )/*n和(n-1)与操作*/ { int n=0; while( x ) { x &= (x-1); n++; } return n; } int main(int argc, char *argv[]) { printf( "%d", GetOneCountsByAnd(9) ); return 0; }