数学-二进制中1的个数-JZ11

博客介绍了如何通过位操作计算一个整数在32位二进制表示中1的个数。提供的代码示例展示了利用n&(n-1)消除最右侧1的方法,通过循环来统计1的总数。这种方法对于理解位操作和优化计算效率有帮助。

描述
输入一个整数,输出该数32位二进制表示中1的个数。其中负数用补码表示。

示例1

输入: 10
返回值: 2

思路

n & n - 1 : 消去数字 n 最右边的 1
二进制数:val :1101000, val-1: 1100111
那么val &(val-1) : 1100000

代码:

public class Solution {
    public int NumberOf1(int n) {
        int res = 0;
        while(n != 0) {
            n = n & (n-1);
            res++;
        }
        return res;
    }
}
好的,完全理解您的要求。我们需要的不只是一份提纲,而是一份充满细节、计算流程、易错点和内在联系的深度解读。 以下是对【第二章:数据的表示与运算】的终极详细解析。 第二章:数据的表示与运算 - 深度解析与实战指南 2.1 数制与编码 1. 进位计数制转换(核心计算能力) * R进制 → 十进制:按权展开求和 * 流程:写出每一位的数码和位权,求所有项的乘积之和。 * 示例: "(1A.3C)16 = 1×16^1 + 116^0 + 3×16^(-1) + 116^(-2) = 16 + 10 + 0.1875 + 0.046875 = (26.234375)10" * 注意:十六进制中 "A-F" 分别对应 "10-15"。 * 十进制 → R进制:整数与小数部分分别转换 * 整数部分(除基取余法): * 流程:将十进制整数不断除以目标基数 R,记录每次的余数,直到商为 0。余数从下往上排列即为结果。 * 示例: "(123)10" → 二进制 123 / 2 = 61 ... 余 1 (最低位) 61 / 2 = 30 ... 余 1 30 / 2 = 15 ... 余 0 15 / 2 = 7 ... 余 1 7 / 2 = 3 ... 余 1 3 / 2 = 1 ... 余 1 1 / 2 = 0 ... 余 1 (最高位) ∴ "(123)10 = (1111011)2" * 小数部分(乘基取整法): * 流程:将十进制小数不断乘以目标基数 R,记录每次的整数部分,直到小数部分为 0 或达到所需精度。整数部分从上往下排列即为结果。 * 示例: "(0.6875)10" → 二进制 0.6875 × 2 = 1.375 ... 取整 1 (最高位) 0.375 × 2 = 0.75 ... 取整 0 0.75 × 2 = 1.5 ... 取整 1 0.5 × 2 = 1.0 ... 取整 1 (最低位) ∴ "(0.6875)10 = (0.1011)2" * ⚠️关键注意点:很多十进制小数(如 "0.1")无法用有限位二进制精确表示,乘基过程会无限循环。这是浮点数精度误差的根源。 2. 校验码(重点:原理与能力对比) 校验码类型 核心原理 计算/判断方法 检错/纠错能力 优点/缺点 关联知识点 奇偶校验码 增加1位,使“1”的个数为奇/偶。 发送/接收方分别计算“1”的个数,与约定奇偶性对比。 码距=2。<br>• 检错:只能发现奇数位错误。<br>• 无法纠错。 实现简单,开销小。<br>无法应对偶数位错误。 最基本的差错控制,是理解码距概念的起点。 海明校验码 在数据位间插入k个校验位,每个校验位负责特定数据位组的奇偶性。 1. 确定校验位数量 2^k ≥ n+k+1。<br>2. 确定校验位位置(2^i)。<br>3. 根据数据位计算各校验位。<br>4. 接收方用新的校验和(伴随式)定位错误位。 码距≥3。<br>• 可检测两位错误(无法定位)。<br>• 可纠正一位错误(精确定位并翻转)。 具备纠错能力。<br>计算相对复杂,数据位越长,所需校验位越多。 将数据位和校验位视为一个系统,通过编码理论(码距)提升可靠性。是理解“冗余”价值的典范。 循环冗余校验(CRC) 将数据视为二进制多项式,除以一个预设的生成多项式,余数作为校验码。 1. 选择生成多项式(如 CRC-16: x^16 + x^15 + x^2 + 1)。<br>2. 在数据后补0(0的个数=生成多项式位数-1)。<br>3. 进行模2除法(异或运算),得到余数。<br>4. 将余数附加到原始数据后发送。<br>5. 接收方用同样方法计算,若余数为0则认为正确。 检错能力极强。<br>• 所有奇数位错误。<br>• 所有双位错误。<br>• 所有长度小于生成多项式阶数的突发错误。 检错率高,硬件实现效率高。<br>主要用于检错,一般不自带纠错功能。 模2运算是核心,不同于算术运算。广泛应用于数据链路层(如以太网帧)、磁盘存储等。 2.2 定点数的表示和运算 1. 真值 ↔ 机器数(补码为核心) * 正数:[X]补 = [X]原 = [X]反 (符号位0,数值位为真值) * 负数: * 快速计算法(常用):对应正数的二进制表示,从右向左找到第一个1,这个1及其右边的位不变,左边的位按位取反(包括符号位)。 * 示例:求 "-10" 的8位补码。 1. "10" 的二进制: "00001010" 2. 从右向左第一个1是第二位,其左边(包括符号位)全部取反: "11110110" 3. ∴ "[-10]补 = 11110110" * 注意:补码的表示范围是 "-2^(n-1)" 到 "+(2^(n-1)-1)"。例如8位补码范围是 "-128" 到 "+127"。 "-128" 没有原码和反码,其补码直接定义为 "10000000"。 2. 补码加减运算 * 流程: "[X±Y]补 = [X]补 + [±Y]补"。符号位与数值位一同参与运算,超出字长的进位直接丢弃。 * 示例: "[X]补 = 0011", "[Y]补 = 1101",求 "X+Y"。 0011 ([X]补) + 1101 ([Y]补) ———————— 10000 (最高位1溢出丢弃) ———————— 0000 ∴ "[X+Y]补 = 0000",结果是 "0"。 * ⚠️ 核心:溢出判断 1. 双符号位判断法(推荐):将符号位扩充为两位( "00"正, "11"负),运算后看结果的两个符号位。 * 结果符号为 "01":正溢出(两个大正数相加)。 * 结果符号为 "10":负溢出(两个大负数相加)。 * 结果符号为 "00" 或 "11":无溢出。 * 示例: "65 + 66"(8位补码,用双符号位表示) "[65]补 = 00 1000001", "[66]补 = 00 1000010" 00 1000001 + 00 1000010 ———————————— 01 0000011 (符号位为01,发生正溢出) 2. 单符号位判断法:最高数值位的进位 "C1" 与符号位的进位 "C0" 异或,若为1则溢出。 "V = C0 ⊕ C1"。 3. 算术移位 * 规则表(极易混淆,必须掌握): 机器数类型 码制 移位操作 填补代码规则 正数 原码、补码、反码 左移/右移 空位补0 负数 原码 左移/右移 空位补0(符号位不变) 负数 补码 左移 低位补0 负数 补码 右移 高位补1(符号位延伸) 负数 反码 左移/右移 空位补1 * 关联:移位运算与乘法器/除法器的硬件实现直接相关。补码算术右移保持符号不变,是实现“除法向零取整”的关键。 2.3 浮点数的表示与运算(IEEE 754标准) 1. 格式深度解析(以单精度为例) "S"(1位) | "E"(8位) | "M"(23位) * 阶码 E:移码表示,偏置值 "Bias = 127"。实际指数 e = E - 127。 * "E" 的范围是 1 到 254。 "E=0" 和 "E=255" 用于表示特殊值。 * 尾数 M:隐藏位技术。规格化二进制数总是 "1.xxxx",所以存储时隐藏最高位的1,只存储小数部分 "xxxx"。计算时必须加回这个1。 * 编码示例:求 "-12.75" 的单精度表示。 1. 符号 S:负号, "S = 1"。 2. 转换为二进制: "12.75 = 1100.11"。 3. 规格化: "1100.11 = 1.10011 × 2^3"。所以 "e = 3"。 4. 计算阶码 E: "E = e + 127 = 3 + 127 = 130"。 "130" 的二进制是 "10000010"。 5. 确定尾数 M:小数部分是 "10011"。在右侧补0至23位: "M = 100 1100 0000 0000 0000 0000"。 6. 最终结果: "1 | 10000010 | 10011000000000000000000" 2. 浮点数加减运算流程(极易出错) 1. 对阶: * 原则:小阶向大阶看齐。 * 操作:阶小的那个数的尾数右移,移去的位可能会丢失精度。右移位数等于两阶码之差 "|ΔE|"。 * ⚠️注意:尾数右移时,低位移出部分要进行舍入处理(如舍入到最近偶数),这是误差来源之一。 2. 尾数相加/减:对阶后,对两个尾数进行运算(用补码)。 3. 规格化:运算结果可能不是规格化形式,需要调整。 * 左规:如果结果尾数的最高位(隐藏位后)不是1(如 "01.xxx" 或 "00.xxx"),则需尾数左移,同时阶码减小。左移几次就减几。 * 右规:如果尾数相加后溢出(如 "10.xxx"),则需尾数右移1位,同时阶码加1。 4. 舍入:在对阶和右规过程中,尾数右移会使低位丢失。IEEE 754定义了多种舍入方法,默认是“向最近偶数舍入”。 5. 溢出判断:规格化后,检查阶码是否超出表示范围( "E ≥ 255" 为上溢, "E ≤ 0" 为下溢)。 2.4 算术逻辑单元(ALU)与知识点关联 * ALU是前述知识的集大成者: * 输入:来自寄存器组的定点二进制数(补码)。 * 操作:根据控制信号,执行加减(补码运算)、与或非(逻辑运算)、移位(算术/逻辑移位)等。 * 输出:运算结果和状态标志。 * 零标志 ZF:结果是否为全0。关联条件跳转指令(如 "jz")。 * 符号标志 SF:结果的最高位(符号位)。关联有符号数比较。 * 进位标志 CF:无符号数运算的最高位进位/借位。关联无符号数比较和大数运算。 * 溢出标志 OF:有符号数运算是否溢出。关联有符号数比较和错误检测。 全章知识点关联图 graph TD A[现实世界数据] --> B{数据类型} B --> C[整数/定点数] B --> D[实数/浮点数] B --> E[字符/非数值数据] C --> C1[无符号数编码] C --> C2[有符号数编码] C2 --> C21[原码/反码/补码] C21 --> C211[补码加减运算] C211 --> C2111[溢出判断(OF)] C --> C3[算术移位] --> C31[硬件乘法/除法基础] D --> D1[IEEE 754标准] D1 --> D11[规格化] D1 --> D12[舍入处理] D1 --> D13[浮点加减运算] --> D131[对阶/尾数运算/规格化] E --> E1[ASCII码] E --> E2[校验码] --> E21[数据可靠性] F[中央处理器(CPU)] --> G[算术逻辑单元(ALU)] G --> C211 G --> D13 G --> H[产生状态标志: ZF, SF, CF, OF] H --> I[控制单元(CU)] --> J[决定程序流程: 条件跳转] C2111 -.-> H D131 -.-> H 总结:第二章的内容环环相扣,从最基础的编码,到定点数的运算(ALU的核心),再到浮点数的表示与处理(解决实数问题),最后通过校验码确保数据可靠传输。理解它们之间的内在联系,是真正学懂计算机组成原理的关键。 拓展丰富
10-17
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值