C语言练习题篇:统计二进制中1的个数

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

要求:

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

比如: 15    0000 1111    4 个 1

在进行代码编写之前,我们先回忆一下整数的二进制表示形式

整数的二进制表示形式:原码、反码、补码

(整数的存储类型是整型,1个整型是4个字节,32个比特位。第一位是符号位,1代表负数,0代表正数。数据在内存中是以二进制补码的形式进行存储的。)

1.正整数的原码、反码、补码是相同的

       原码:根据正整数直接写出二进制序列

2.负整数的原码、反码、补码需要计算

       原码:根据正整数直接写出二进制序列

       反码:符号位不变,其他位按位取反

       补码:反码+1

我们可以首先写出代码的主体部分

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int count_bit_one(int m)
{
	int count = 0;//用来统计二进制中1的个数

	return count;
}
int main()
{
	int n = 0;
	scanf("%d", &n);
	int ret = count_bit_one(n);
	printf("%d\n", ret);
	return 0;
}

方法一: 

二进制想得到它的每一位,我们应该怎么得到呢?

类比十进制得到它的每一位,我们是怎么得到的?

假设1234,我们要怎么得到他的每一位

1234 % 10 =4

1234 / 10 =123

123 % 10 = 3

123 / 10 =12 

12 % 10 =2

12 / 10 = 1

1 % 10 = 1

1 / 10 = 0

根据十进制得到他的每一位,我们来模拟一下二进制

假设15,我们要得到他的每一位

15                    1111

15 % 2 =1        

15 / 2 = 7         0111

7 % 2 = 1

7 / 2 = 3           0011    

3 % 2 = 1

3 / 2 = 1          0001

1 % 2 = 0

1 / 2 = 0 

以上这段描述,可以用while循环来实现

while (m)
	{
		if (m % 2 == 1)
			count++;
		m /= 2;
	}

 整体代码如下:

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int count_bit_one(int m)
{
	int count = 0;//用来统计二进制中1的个数
	while (m)
	{
		if (m % 2 == 1)
			count++;
		m /= 2;
	}
	return count;
}
int main()
{
	int n = 0;
	scanf("%d", &n);
	int ret = count_bit_one(n);
	printf("%d\n", ret);
	return 0;
}

 此时此刻,想必聪明的同学,已经想到了,万一输入的数字是负数呢 ?

这时候,我们仔细一想,整数是有符号位的,我们可以传无符号的数字,即使用unsigned。

int count_bit_one(unsigned int m)

 完整代码如下:

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int count_bit_one(unsigned int m)
{
	int count = 0;//用来统计二进制中1的个数
	while (m)
	{
		if (m % 2 == 1)
			count++;
		m /= 2;
	}
	return count;
}
int main()
{
	int n = 0;
	scanf("%d", &n);
	int ret = count_bit_one(n);
	printf("%d\n", ret);
	return 0;
}

 这时候,输入负数,程序也可以得到正确答案了。

方法二:

我们可以通过得到最后一位是什么和右移即可。由学习的知识我们可以得到,可以按位与(&)1来得到最低位。

15 的二进制序列是00000000000000000000000000001111
1 的二进制序列是00000000000000000000000000000001


15 和 1 按位与
& ——对应二进制位有0则为0,两个同时为1,才是1
00000000000000000000000000001111
00000000000000000000000000000001
00000000000000000000000000000001
得到15的二进制序列的最后一位是1

m & 1

然后我们可以根据for循环来不断右移,从而得到最后一位。

    int i = 0;
	for (i = 0; i < 32; i++)
	{
		if (((m >> i) & 1) == 1)
			count++;
	}

完整代码如下:

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int count_bit_one(int m)
{
	int count = 0;//用来统计二进制中1的个数
	int i = 0;
	for (i = 0; i < 32; i++)
	{
		if (((m >> i) & 1) == 1)
			count++;
	}
	return count;
}
int main()
{
	int n = 0;
	scanf("%d", &n);
	int ret = count_bit_one(n);
	printf("%d\n", ret);
	return 0;
}

缺陷:不论输入数字是多少,都会循环32次。因此效率比较低。

方法三: 

有一个公式: n = n & ( n - 1 ):会让 n 的二进制中最右边的 1 消失

假设 n 为14

n     的二进制序列:00000000000000000000000000001110

n - 1的二进制序列:00000000000000000000000000001101

& ——对应二进制位有0则为0,两个同时为1,才是1

n             为00000000000000000000000000001110

n-1          为 00000000000000000000000000001101

n             为00000000000000000000000000001100

n - 1        为00000000000000000000000000001011

n             为00000000000000000000000000001000

n - 1        为00000000000000000000000000000111

n            为00000000000000000000000000000000

 即假如 n 中有 m 个 1 ,则 n = n & ( n - 1 ) 每执行一次,去掉一个 1 ;总共执行 m 次,n 会变为0;

即可以用while循环来判断,直至 n = 0

while (m)
	{
		m = m & (m - 1);
		count++;
	}

完整代码如下:

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int count_bit_one(int m)
{
	int count = 0;//用来统计二进制中1的个数
	while (m)
	{
		m = m & (m - 1);
		count++;
	}
	return count;
}
int main()
{
	int n = 0;
	scanf("%d", &n);
	int ret = count_bit_one(n);
	printf("%d\n", ret);
	return 0;
}

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

囚徒玩电脑

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值