一万种方法计算32位整型数中的'1'的个数

 方法一:

   自然智慧就可以想到的办法,没什么好说的,直接上代码了。

void bit_count1(unsigned int num)//②可以计算所有整数"1"的个数(循环)
{
	unsigned int count = 0;
	for (size_t i = 0; i < 8 * sizeof(num); ++i)
	{
		if (num & 1 << i)
			count++;
	}
	cout << count << endl;
}

方法二:


     那上面图与下面的程序一起来进行分析,每次进入循环,那么就让count++,然后将num的二进制序列中从低位起的第一个1置零;直到num的值变为零结束循环。(ps:注意这里传进来的参数是无符号整数。你们懂得,即使负数传进来变成一个很大的正整数,也不影响计算该负数二进制序列中"1"的个数)

void bit_count2(unsigned int num)//①能计算整数的"1"的个数
{
	unsigned int count = 0;
	while (num > 0)
	{
		count++;
		num &= num - 1;
	}
	cout << count << endl;
}

方法三:

    

   依然拿上面的例子结合下面的程序进行分析:通过下面的公式可以计算到

   count = 2*64^5+6*64^4+6*64^3+6*64^2+5*64^1+3*64^0。

 1.  计算到这里似乎不能玩下去了,但是有那么一个公式n^k % (n-1) = 1,其中n和k为任意自然数,证明如下:n^k % (n-1) = ( (n-1) * n^(k-1) + n^(k-1) ) % (n-1)

                                                    = n^(k-1) % (n-1)

                                                    = ......

                                                    = n^0 % (n-1) = 1

  所以 count % 63的结果就等于各系数之和。

2. 那么你可能还会有一个疑问,为什么用64作为权值而不用32或其它值呢?

   答:因为我们计算32位整数的"1"的个数,那么最极端的情况是会出现32个"1",所以32做权值不合适。如果以128作为权值可以吗?答案是理论上可以。那么下面的八进制要改成00004020100040201,而且要控制移动七次,所以没必要以128做权值。综上,以64作为权值最合适。

void bit_count3(unsigned int num)
{
	unsigned int count = 0;
	count = (num & 010101010101) + (num >> 1 & 010101010101) + (num >> 2 & 010101010101) +
		(num >> 3 & 010101010101) + (num >> 4 & 010101010101) + (num >> 5 & 010101010101);
	cout << count % 63 << endl;
}
方法四:

    这种方法其实是方法三的改进,使得公式只需要三项就能完成初步计算。我们注意到,6位数中最多只有6个'1',也就是000110,只需要3位有效位。上面的式子实际上是以1位为单位提取出'1'的个数再相加求和求出6位中'1'的总个数的,所以用的是&(000001)。如果以3位为单位算出'1'的个数再进行相加的话,那么就完全可以先加后MASK。

void bit_count4(unsigned int num)
{
	unsigned int count = 0;

	count = (num & 011111111111) + (num >> 1 & 011111111111) + (num >> 2 & 011111111111);
	count = count + (count >> 3) & 030707070707;
	cout << count % 63 << endl;
}
方法五:

   下面这个方法就牛逼了,假如有一个3位2进制数是4a+2b+c,我们想要求的是a+b+c,n>>1的结果是2a+b,n>>2的结果是a。

 于是: (4a+2b+c) - (2a+b) - (a) = a + b + c
void bit_count5(unsigned int num)
{
	unsigned int count = 0;
	count = num - (num >> 1 & 033333333333) - (num >> 2 & 011111111111);
	count = count + (count >> 3) & 030707070707;
	cout << count % 63 << endl;
}



猜你喜欢

转载自blog.csdn.net/qq_39290388/article/details/79988733