当前位置: 首页 > ai >正文

什么是原码、反码与补码?

在计算机科学中,数值在内存中的存储和表示是通过不同的编码系统实现的。这些编码系统主要包括原码、反码和补码,它们各自有不同的特点和用途。本指南将详细介绍这些编码系统,帮助您深入理解计算机如何表示和处理数值。

1. 原码(True Form)

原码是最直观的二进制表示方法,直接将数字的绝对值转换为二进制,然后在最高位添加符号位(0表示正数,1表示负数)。

定义与规则

  • 最高位为符号位:0代表正数,1代表负数
  • 其余位表示数值的绝对值

示例

对于8位二进制表示:

+43 的原码:0 0101011 (符号位为0,后面是43的二进制)
-43 的原码:1 0101011 (符号位为1,后面是43的二进制)

特点

  1. 直观性:容易理解和手动转换
  2. 范围:对于n位二进制,范围是 -(2^(n-1)-1) 到 +(2^(n-1)-1)
  3. 缺点:存在两个零(+0和-0),且在算术运算中需要特殊处理

在8位表示中:

  • +0 的原码:0 0000000
  • -0 的原码:1 0000000

原码的局限性

原码在进行算术运算时存在诸多不便:

  • 加法和减法需要比较绝对值大小
  • 需要单独处理符号
  • 存在两个零的表示,浪费了一个编码

2. 反码(One's Complement)

反码是一种改进的编码方式,对于负数,除符号位外,其余位取原码的按位取反(0变1,1变0)。

定义与规则

  • 正数的反码等于其原码
  • 负数的反码是符号位保持不变,其余位按位取反

示例

对于8位二进制表示:

+43 的反码:0 0101011 (与原码相同)
-43 的反码:1 1010100 (符号位为1,其余位取反)

特点

  1. 弥补部分缺陷:使得加减法运算规则更统一
  2. 范围:与原码相同
  3. 依然存在两个零:+0(0 0000000)和-0(1 1111111)

反码的加法

在反码表示中,加法操作得到简化:

  1. 直接按位相加
  2. 如果有进位到符号位之外,则需要将这个进位加回到结果的最低位(称为"端进位循环")

例如:计算 +15 + (-10)

+15 的反码:0 0001111
-10 的反码:1 1110101
按位相加:  1 0000100 (产生进位)
进位回卷:  0 0000101 = +5 (正确结果)

3. 补码(Two's Complement)

补码是现代计算机普遍采用的数值表示方法,它解决了原码和反码的主要缺点。

定义与规则

  • 正数的补码等于其原码
  • 负数的补码等于其反码加1(或者直接从原码取反后加1)

示例

对于8位二进制表示:

+43 的补码:0 0101011 (与原码相同)
-43 的补码:1 1010101 (反码1 1010100加1,或直接原码除符号位外取反后加1)

特点

  1. 统一的零表示:只有一个零(0 0000000)
  2. 简化计算:加减法运算更加自然,无需额外处理
  3. 范围不对称:对于n位二进制,范围是 -2^(n-1) 到 +(2^(n-1)-1) (例如8位补码的范围是 -128 到 +127)

补码的特殊情况

在8位补码表示中,-128(1 0000000)是一个特殊值,它没有对应的正数表示,因为+128超出了8位补码的正数表示范围。

补码的加减法

补码的一个主要优势是简化了算术运算:

  1. 加法:直接按位相加,忽略最高位的进位
  2. 减法:被减数加上减数的补码(等价于加上减数的负数)

例如:计算 +15 + (-10)

+15 的补码:0 0001111
-10 的补码:1 1110110
按位相加:  1 0000101
丢弃进位:  0 0000101 = +5 (正确结果)

4. 移码(Excess Code)

移码是另一种二进制表示法,主要用于表示浮点数的指数部分。

定义与规则

移码是在真值(实际值)的基础上加上一个偏移量(通常是2^(n-1))后得到的编码。

示例

对于8位二进制表示,偏移量为128(2^7):

-43 的移码:128 - 43 = 85 = 0 1010101
+43 的移码:128 + 43 = 171 = 1 0101011

特点

  1. 便于比较大小:移码的二进制表示可以直接比较大小(无需考虑符号)
  2. 广泛用于浮点数指数部分:如IEEE 754标准
  3. 零的表示:通常为偏移量的二进制表示

应用场景

移码最常见的应用是在IEEE 754浮点数标准中表示指数部分:

  • 单精度浮点数使用8位移码,偏移量为127
  • 双精度浮点数使用11位移码,偏移量为1023

5. 各编码系统的比较

下面通过一个表格对比不同编码系统的特点:

特性原码反码补码移码
符号位0为正,1为负0为正,1为负0为正,1为负无显式符号位
负数表示符号位为1,余位为绝对值符号位为1,余位按位取反反码加1真值加偏移量
零的表示+0和-0两种表示+0和-0两种表示唯一表示:全0偏移量的二进制表示
数值范围(8位)-127到+127-127到+127-128到+127-128到+127
加法实现复杂,需要特殊处理需要端进位循环简单,直接按位相加简单,直接按位相加
主要用途较少使用历史上使用整数表示的主流方式浮点数指数部分

6. 在Java中的应用

Java的整数类型(byte、short、int、long)都使用补码表示。以下是一些操作补码的例子:

获取一个数的补码表示

public static void printTwosComplement(int number, int bits) {// 创建一个指定位数的掩码int mask = (1 << bits) - 1;// 应用掩码获取指定位数的补码表示int twosComp = number & mask;// 转换为二进制字符串并补齐前导零String binary = Integer.toBinaryString(twosComp);while (binary.length() < bits) {binary = "0" + binary;}System.out.println(number + " 的 " + bits + " 位补码表示: " + binary);
}

从补码还原为原始值

public static int fromTwosComplement(String binaryStr) {// 检查是否为负数(最高位为1)if (binaryStr.charAt(0) == '1') {// 负数情况:按位取反后加1,再加负号char[] chars = binaryStr.toCharArray();for (int i = 0; i < chars.length; i++) {chars[i] = (chars[i] == '0') ? '1' : '0';}String invertedStr = new String(chars);return -(Integer.parseInt(invertedStr, 2) + 1);} else {// 正数情况:直接转换return Integer.parseInt(binaryStr, 2);}
}

7. 编码转换算法

下面是各种编码之间转换的算法实现:

原码转补码

public static String trueFormToTwosComplement(String trueForm) {if (trueForm.charAt(0) == '0') {// 正数:原码等于补码return trueForm;} else {// 负数:除符号位外按位取反后加1char[] result = trueForm.toCharArray();for (int i = 1; i < result.length; i++) {result[i] = (result[i] == '0') ? '1' : '0';}// 加1操作for (int i = result.length - 1; i > 0; i--) {if (result[i] == '0') {result[i] = '1';break;} else {result[i] = '0';}}return new String(result);}
}

补码转原码

public static String twosComplementToTrueForm(String twosComp) {if (twosComp.charAt(0) == '0') {// 正数:补码等于原码return twosComp;} else {// 负数:除符号位外按位取反后加1char[] result = twosComp.toCharArray();// 减1操作for (int i = result.length - 1; i > 0; i--) {if (result[i] == '1') {result[i] = '0';break;} else {result[i] = '1';}}// 按位取反for (int i = 1; i < result.length; i++) {result[i] = (result[i] == '0') ? '1' : '0';}return new String(result);}
}

8. 实际应用示例

例1:温度传感器数据处理

假设一个8位温度传感器使用补码表示-50°C到+80°C的温度:

public class TemperatureSensor {public static int decodeTemperature(byte rawData) {// 直接将byte解释为有符号数(Java已使用补码)return (int)rawData;}public static byte encodeTemperature(int temperature) {// 检查范围if (temperature < -128 || temperature > 127) {throw new IllegalArgumentException("Temperature out of range");}// 直接转换为byte(Java自动使用补码)return (byte)temperature;}public static void main(String[] args) {// 编码温度byte encoded = encodeTemperature(-15);System.out.println("编码后的二进制: " + String.format("%8s", Integer.toBinaryString(encoded & 0xFF)).replace(' ', '0'));// 解码温度int decoded = decodeTemperature(encoded);System.out.println("解码后的温度: " + decoded + "°C");}
}

例2:计算机网络中的检验和

在网络协议中,常使用一种特殊的补码运算来计算校验和:

public class Checksum {public static short calculateChecksum(byte[] data) {int sum = 0;// 将数据按16位字进行求和for (int i = 0; i < data.length - 1; i += 2) {sum += ((data[i] & 0xFF) << 8) | (data[i + 1] & 0xFF);}// 如果长度为奇数,处理最后一个字节if (data.length % 2 != 0) {sum += (data[data.length - 1] & 0xFF) << 8;}// 将高16位加到低16位while ((sum >> 16) > 0) {sum = (sum & 0xFFFF) + (sum >> 16);}// 取反得到校验和return (short)(~sum);}
}

9. 位操作的优化

在处理二进制编码时,掌握一些位操作技巧可以提高效率:

判断一个数是否为负数(补码表示)

boolean isNegative = (number & (1 << (bits - 1))) != 0;

获取补码表示的绝对值

public static int absoluteValue(int number) {int mask = number >> 31;return (number ^ mask) - mask;
}

不使用if语句计算补码的相反数

public static int negate(int number) {return ~number + 1;
}

10. 总结

理解原码、反码和补码对于深入学习计算机科学和优化算法至关重要:

  1. 原码是最直观的表示方法,但在运算中不方便
  2. 反码改进了部分问题,但仍存在两个零的表示
  3. 补码解决了大多数问题,是现代计算机普遍采用的方案
  4. 移码主要用于浮点数表示和比较

掌握这些编码系统之间的关系和转换方法,有助于理解计算机如何处理数字以及解决相关的编程问题。

在实际应用中,大多数情况下我们不需要直接操作这些编码形式,因为高级编程语言已经封装了相关细节。但在一些特定领域,如嵌入式系统编程、网络协议实现、密码学和底层优化等方面,这些知识仍然非常重要且实用。

http://www.xdnf.cn/news/3952.html

相关文章:

  • 数据管理能力成熟度评估模型(DCMM)全面解析:标准深度剖析与实践创新
  • 【Java项目脚手架系列】第二篇:JavaWeb项目脚手架
  • js获取明天日期、Vue3大菠萝 Pinia的使用
  • 【Linux系统篇】:Linux线程互斥---如何用互斥锁守护多线程程序
  • MCUboot 中的 BOOT_SWAP_TYPE_PERM 功能介绍
  • (undone) MIT6.S081 2023 学习笔记 (Day11: LAB10 mmap)
  • Redis数据结构ZipList,QuickList,SkipList
  • 《数字图像处理(面向新工科的电工电子信息基础课程系列教材)》封面颜色空间一图的选图历程
  • 电磁气动 V 型球阀:颗粒状矿浆与煤黑水介质处理的革命性解决方案-耀圣
  • GAF-CNN-SSA-LSSVM故障诊断/分类预测,附带模型研究报告(Matlab)
  • 学习海康VisionMaster之亮度测量
  • 图像批量处理工具 界面直观易懂
  • TCP 与 UDP报文
  • Doo全自动手机壳定制系统
  • 【AI大模型学习路线】第一阶段之大模型开发基础——第四章(提示工程技术-1)Zero-shot与Few-shot。
  • 基于 jQuery 实现灵活可配置的输入框验证功能
  • 模型 - Xiaomi MiMo
  • Sui 上线两周年,掀起增长「海啸」
  • 【PostgreSQL数据分析实战:从数据清洗到可视化全流程】5.3 相关性分析(PEARSON/SPEARMAN相关系数)
  • MongoDB入门详解
  • 永磁同步电机控制算法--基于PI和前馈的位置伺服控制
  • C 语言 第五章 指针(7)
  • LLM提示词设计及多轮对话优化策略在心理健康咨询场景中的应用研究
  • 从零开始学习RAG
  • Jetpack Compose 响应式布局实战:BoxWithConstraints 完全指南
  • 从0到1快速了解Redis数据库
  • 数字化转型:激活存量,引爆增量的三大核心逻辑
  • Spring-使用Java的方式配置Spring
  • 基于Python+MongoDB猫眼电影 Top100 数据爬取与存储
  • 常用CPU、GPU、NPU、DSP、ASIC等芯片区别介绍