统计整数在内存中二进制表示1的个数---C语言

一、问题描述

题目:统计二进制中1的个数。

          写一个函数返回参数二进制中 1 的个数。

示例: 15    0000 1111    4 个 1

             -1   ................     32个1

示例分析:

二进制负数,在内存中以其补码的方式进行存储。
-1的原码:10000000 00000000 00000000 00000001(第一位为符号位)
-1的反码:11111111 11111111 11111111 11111110
-1的补码:11111111 11111111 11111111 11111111
         所以,-1的二进制中有32个1

原码、补码、反码
    原码:数的二进制表示
    反码:原码除符号位外的位数按位取反
    补码:反码 + 1

二、问题分析及C语言程序描述

解法一

//c语言程序

int count(int result)
{
	//1.对result模2统计1的个数
	int counter = 0;
	while (result)
	{
		if (result % 2 == 1)
		{
			counter++;
		}
		result /= 2;
	}
	return counter;
}

//思路:将所给数据按位模2,如果余数为1,counter++同时除以2去掉该位数,直到原数位0.

//结果分析

 输入:6    输出:2
 输入:-1   输出:0    (error)

由于,负数在计算机中以期补码的形式存储。而该方法直接对所给整数对2取模,因此此方法不适用于统计一个负数在内存中的二进制数中1的个数。

解法二

//c程序

int count(int result)
{
	int counter = 0;
	int i = 0;
    //int类型数据在内存中占32位
	for (i = 0; i < 32; i++)
	{
		if (((result >> i) & 1) == 1)
		{
			counter++;
		}
	}
	return counter;
}
//思路:将该数据的二进制补码的每位与1相与,如果为1表示该为为1,counter++。每判断一位,将该二进制数右移一位,以确保每一位数都进行判断。

//结果分析

输入:6    输出:2
输入:-1   输出:32

虽然该方法无论负数还是正数均可进行计算,但是由于无论何种情况,该方法中的for循环都必须执行32次,时间复杂度较高,程序运行效率较低。

解法三

//c程序

int count(int result)
{
	int counter = 0;
	while (result)
	{
		result = result & (result - 1);
		counter++;
	}
	return counter;
}

//思路:逐一消去二进制数中的1,每消掉一个counter++一次。
        将一个数的二进制数与其减一后的二进制数相遇的结果为,将该数中的从右至左的第一个1去掉的结果相同。

//结果分析
输入:6    输出:3
输入:-1   输出:32

该方法即解决了方法二中无法对负数进行判断的问题,同时也解决了方法二中程序效率较低的问题。

 

你可能感兴趣的:(其他,算法)