探秘C语言经典题目:如何求解整数二进制中1的个数

news2024/12/25 13:57:39

在这里插入图片描述

本篇博客会讲解一道经典的题目:求一个整数二进制中1的个数。阅读本篇博客前,需要你对C语言如何进行二进制位操作有一定的了解,如果还不太了解的话,可以阅读一下我的这篇博客。

我们假设有一个int类型的整数n,我们知道,n在内存中是以二进制的补码的形式存储的。这个补码的二进制,是由0和1组成的,究竟有多少个1呢?我们能不能写个程序来求一下?

“&1”的妙用

如果你认真读了我讲解位操作符的那篇博客,应该知道n&1代表了啥。不知道也没关系,可以来观察一下:

1: 00000000000000000000000000000001
n: 11000111101011101010011110110111

左边的31位,由于“任何数 & 0”都会得到0,所以最终的结果只由最右边的1位决定。分类讨论一下:

  1. 如果n的最右边1位是0,则按位与的结果是0。
  2. 如果n的最右边1位是1,则按位与的结果是1。

再提炼一下,n & 1的结果是1,说明n的最右边1位是1,否则n的最右边1位是0,换句话说,n & 1的结果是n最右边的1位。

那么我们就有思路了:我们通过(n >> i) & 1就能拿到第i位的值,统计其中有几个1就行了。

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

从“%10 /10”到“%2 /2”

看到“%10 /10”,大家会联想到啥?如果你做题做多了,会第一时间反应到:%10可以拿到一个十进制数的最后一位,而/10会把最后一位去掉!比如:

123 % 10 = 3
123 / 10 = 12
12 % 10 = 2
12 / 10 = 1
1 % 10 = 1
1 / 10 = 0

在n变成0之前,就可以拿到十进制中的每一位。那如果是拿到二进制中的每一位呢?“%2 /2”不就行了!不过需要注意的是,“%2 /2”的操作必须对无符号整数进行,如果对有符号整数,遇到负数时结果是错的。比如,-1的补码有32个1,但是使用“%2/2”操作并不会操作32次,第一次/2就变成0了,结果是错的。

int GetNumOf1(unsigned int n)
{
	int count = 0;
	while (n)
	{
		if (n % 2 == 1)
			++count;

		n /= 2;
	}
	return count;
}

神奇的“n &= n - 1”

n &= n - 1的效果是去掉n的二进制位中最右边的那个1。比如:

n: 00000000000000000010001100001001
n &= n - 1
n: 00000000000000000010001100001000
n &= n - 1
n: 00000000000000000010001100000000
n &= n - 1
n: 00000000000000000010001000000000
n &= n - 1
n: 00000000000000000010000000000000
n &= n - 1
n: 00000000000000000000000000000000

由于一开始的二进制中有5个1,所以执行5次n &= n - 1后,n就变成0了。

这个思路实现成代码如下:

int GetNumOf1(unsigned int n)
{
	int count = 0;
	while (n)
	{
		++count;
		n &= n - 1;
	}
	return count;
}

总结

  1. n & 1的操作可以得到n的补码的二进制最右边的那一位数。
  2. 反复“%2 /2”可以得到二进制中的每一位。
  3. n &= n - 1的效果是去掉n的二进制位中最右边的那个1。

感谢大家的阅读!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/485014.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

12. Transformer(上)

P32 Transformer&#xff08;上&#xff09; 视频链接 P32 Transformer&#xff08;上&#xff09; Seq2seq应用: Seq2seq结构:

武忠祥老师每日一题||定积分基础训练(二)

仍是上一节中提到的基本思想 武忠祥老师每日一题||定积分基础训练&#xff08;一&#xff09; 在这个题中&#xff0c;M和N可以利用奇偶性判断。 如下&#xff1a; 从上可知&#xff0c; M ∫ − π 2 π 2 1 d x M\int_{-\frac{\pi}{2}}^{\frac{\pi}{2}}1\,{\rm d}x M∫−…

The 1st Universal Cup Stage 13: Iberia, Apr 22-23, 2023 题解

D. XOR Determinant You are given two arrays b and c of length n, consisting of non-negative integers. Construct n n matrix A as Aij bi ⊕ cj . Find the determinant of A modulo 998 244 353 考虑 A i j ∑ k b i , k c j , k p A_{ij}\sum_k b_{i,k}{c_{j,k}…

基于GWO灰狼优化算法的城市路径优化问题GWO-TSP(MATLAB程序)

资源地址&#xff1a; 基于GWO灰狼优化算法的城市路径优化问题GWO-TSP(MATLAB程序&#xff09;资源-CSDN文库 主要内容&#xff1a; 主要采用灰狼优化算法对城市间的路径进行规划。城市分布图如图所示。 部分代码&#xff1a; % 产生问题模型 model CreateModel(Oliver30.…

p70 内网安全-域横向内网漫游 Socks 代理隧道技术(NPS、FRP、CFS 三层内网漫游)

数据来源 本文仅用于信息安全学习&#xff0c;请遵守相关法律法规&#xff0c;严禁用于非法途径。若观众因此作出任何危害网络安全的行为&#xff0c;后果自负&#xff0c;与本人无关。 ​ 必要基础知识点&#xff1a; 内外网简单知识内网 1 和内网 2 通信问题正向反向协议通…

linux用户管理指令

这里写自定义目录标题 一 增加新用户及密码二 切换用户三 userdel 删除用户四 查看用户登录信息五 让普通用户成为管理员1. 修改环境配置文件2.设置用户和密码 六 查看创建哪些用户 一 增加新用户及密码 useradd:加用户名 passwd&#xff1a;加用户密码 [rootlocalhost ~]# u…

HBASE整理

HBASE整理 一、HBASE由来 思考: HDFS主要适用于什么场景呢? 具有高的吞吐量 适合于批量数据的处理操作思考: 如果想在HDFS上, 直接读取HDFS上某一个文件中某一行数据, 请问是否可以办到呢? 或者说, 我们想直接修改HDFS上某一个文件中某一行数据,请问是否可以办到呢?HDFS并…

【Python】芜湖市空气质量指数可视化(散点图、分类散点图、单变量分布图、线性回归拟合图、相关性热力图)

【Python】芜湖市空气质量指数可视化 本文仅供学习参考&#xff0c;如有错误&#xff0c;还请指正&#xff01; 一、简介 空气质量指数&#xff08;Air Quality Index&#xff0c;AQI &#xff09;简而言之就是能够对空气质量进行定量描述的数据。空气质量(Air Quality )的好坏…

《SQLi-Labs》02. Less 6~10

sqli Less-6知识点题解 Less-7题解 Less-8题解 Less-9知识点题解 Less-10题解 sqli。开启新坑。 Less-6 知识点 布尔盲注。与 Less-5 基本相同。这里只简略写大致步骤。 length() 函数&#xff1a;返回字符串所占的字节数。ascii() 函数&#xff1a;返回字符串最左字符的ASC…

OpenGL开发必过的坎------开发环境的准备(Windows10)

前言 图形编程一直以来都是计算机科学中最具挑战性的主题之一。随着限制VR技术的兴起&#xff0c;越来越多的公司开始涉足VR领域。目前来看使用最多的是Unity3d来开发&#xff0c;但是像浏览器&#xff0c;将2D应用3D化&#xff08;把2D的应用界面投到一个3D的场景中&#xff…

FilmConvert Nitrate for Mac(fcpx/胶片模拟调色Pr/AE插件)

FilmConvert Nitrate是一款针对视频后期处理的插件&#xff0c;可用于颜色校正和外观看调整。它提供了各种预设&#xff0c;以方便用户足够快速地修改视频的外观&#xff0c;并还包含一个自定义工具集&#xff0c;以方便用户可以调整多个参数来达到他们所需要的效果。 该插件支…

SpringBoot + Druid DataSource 实现监控 MySQL 性能

1 添加依赖 <properties><java.version>1.8</java.version><alibabaDruidStarter.version>1.2.11</alibabaDruidStarter.version> </properties><dependency><groupId>com.alibaba</groupId><artifactId>druid-s…

Python基础合集 练习24 (程序调试)

assert expression[,arguments] expression条件表达式语句,如果表达式的值为真,则程序会继续执行下去,如果值为假则程序抛出Assertionerror错误,并输出指定的参数内容 arguments可选参数 if not expression: raise AssertionError(argument) def num_ca(): book int(inpu…

Rust 一门赋予每个人构建可靠且高效软件能力的语言

目录 Rust 安装 尝试 hello, world 编译 链接出错 开启 Rust 之旅 官方教程 《Rust 程序设计语言》 《通过例子学 Rust》 核心文档 标准库 版本指南 CARGO 手册 RUSTDOC 手册 RUSTC 手册 编译错误索引表 非官方翻译教程 Rust 程序设计语言 简体中文版 通…

543. 二叉树的直径【71】

难度等级&#xff1a;容易 上一篇算法&#xff1a; 199. 二叉树的右视图【111】 力扣此题地址&#xff1a; 543. 二叉树的直径 - 力扣&#xff08;Leetcode&#xff09; 1.题目&#xff1a;543. 二叉树的直径 给定一棵二叉树&#xff0c;你需要计算它的直径长度。一棵二叉树的…

玩一玩 Ubuntu 下的 VSCode 编程

一&#xff1a;背景 1. 讲故事 今天是五一的最后一天&#xff0c;想着长期都在 Windows 平台上做开发&#xff0c;准备今天换到 Ubuntu 系统上体验下&#xff0c;主要是想学习下 AT&T 风格的汇编&#xff0c;这里 Visual Studio 肯定是装不了了&#xff0c;还得上 VSCode…

Spring:依赖注入的方式(setter注入、构造器注入、自动装配、集合注入)

依赖注入的方式有setter注入、构造器注入、自动装配、集合注入 首先&#xff0c;Maven项目pom.xml依赖包如下&#xff1a; pom.xml <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:…

Servlet中转发和重定向的区别

什么是转发&#xff0c;重定向&#xff1f; 转发和重定向都是用于在服务器和浏览器之间进行页面跳转的方式。 转发是在服务器内部进行的&#xff0c;当一个Servlet接收到请求后&#xff0c;它可以将请求转发给另一个Servlet或JSP页面来处理请求&#xff0c;但是浏览器不知道这…

C语言-学习之路-04

C语言-学习之路-04 数组与字符串一维数组一维数组的定义和使用一维数组的初始化数组名一维数组练习 二维数组二维数组的定义和使用二维数组的初始化数组名 字符数组与字符串字符串的输入输出随机数字符串处理函数 数组与字符串 数组&#xff1a;为了方便处理数据把具有相同类型…

等保工作的定级指南文件

定级主要依据国家标准信息安全技术网络安全等级保护基本要求来整改。有关等保工作流程和明细,请见:https://luozhonghua.blog.csdn.net/article/details/130465356?spm=1001.2014.3001.5502 5网络安全等级保护概述 5.1等级保护对象 等级保护对象是指网络安全等级保护工作中…