找回密码
 立即注册
首页 业界区 业界 原码、反码、补码

原码、反码、补码

判涔 2025-6-2 22:48:06
目录

  • 1. 原码(Sign-Magnitude)

    • 定义
    • 特点
    • 使用场景

  • 2. 反码(Ones' Complement)

    • 定义
    • 特点
    • 使用场景

  • 3. 补码(Two's Complement)

    • 定义
    • 特点
    • 使用场景

  • 4. 为什么需要反码和补码?

    • (1)解决 +0 和 -0 问题
    • (2)统一加减运算
    • (3)硬件优化

  • 5. 实际应用示例

    • (1)Java 中的 byte 类型
    • (2)无符号转换
    • (3)网络协议 & 文件解析

  • 6. 总结
  • 示例

    • 为什么 在Java中 0xFC 变成 -4?
    • 示例代码
    • 如何正确查看 0xFC?
    • 关键点总结
    • 为什么 Java 的 byte 是有符号的?
    • 适用场景


在计算机中,原码、反码、补码 是表示有符号整数的三种方式,主要用于解决 负数存储和运算 的问题。它们的定义、作用及使用场景如下:
Java 大端、小端存储,short、int 转 byte数组,& 0xFF 清除高位符号扩展,保留低 8 位。
1. 原码(Sign-Magnitude)

定义


  • 最高位表示符号(0 为正,1 为负),其余位表示数值。
  • 例如,8 位二进制:

    • +5 的原码:0000 0101
    • -5 的原码:1000 0101

特点


  • 直观,人类容易理解。
  • 问题

    • +0 和 -0 不唯一(0000 0000 和 1000 0000)。
    • 加减运算复杂,需要额外判断符号位。

使用场景


  • 早期计算机(如 IBM 701)使用原码,但现代计算机基本不再使用。
2. 反码(Ones' Complement)

定义


  • 正数:反码 = 原码。
  • 负数:符号位不变,其余位 按位取反
  • 例如:

    • +5 的反码:0000 0101(同原码)
    • -5 的反码:1111 1010(符号位 1,数值位取反)

特点


  • 解决了 +0 和 -0 的问题(反码下 -0 是 1111 1111,但仍有冗余)。
  • 缺点

    • 加减运算仍需处理进位(如 -5 + 5 = 1111 1010 + 0000 0101 = 1111 1111,即 -0)。
    • 硬件实现复杂。

使用场景


  • 早期计算机(如 PDP-1)使用反码,但已被补码取代。
3. 补码(Two's Complement)

定义


  • 正数:补码 = 原码。
  • 负数:反码 + 1(即 取反后加 1)。
  • 例如:

    • +5 的补码:0000 0101(同原码)
    • -5 的补码:
      1. 原码:1000 0101
      2. 反码:1111 1010
      3. 补码:1111 1011 (反码 + 1)
      复制代码

特点


  • 解决了 +0 和 -0 问题(补码下 -0 表示为 0000 0000,与 +0 相同)。
  • 加减运算统一(直接按二进制加法计算,无需额外处理符号位)。
  • 硬件实现简单(只需加法器,无需额外电路)。
使用场景


  • 现代计算机(包括 Java)全部使用补码存储有符号整数
  • 例如:

    • Java 的 byte、short、int、long 均用补码表示。
    • 0xFC(1111 1100)在 byte 类型中表示 -4(因为补码计算:~1111 1100 + 1 = 0000 0100,即 -4)。

4. 为什么需要反码和补码?

(1)解决 +0 和 -0 问题


  • 原码和反码中,+0 和 -0 的表示不同,导致比较和运算复杂。
  • 补码中 0 只有一种表示(0000 0000),简化逻辑。
(2)统一加减运算


  • 补码下,减法可以转换为加法(A - B = A + (-B)),硬件只需加法器。

    • 例如:5 - 3 = 5 + (-3):
      1. 5 的补码:0000 0101
      2. -3 的补码:1111 1101
      3. 相加:0000 0101 + 1111 1101 = 0000 0010 (即 2)
      复制代码

(3)硬件优化


  • 补码运算无需额外判断符号位,减少电路复杂度。
5. 实际应用示例

(1)Java 中的 byte 类型
  1. byte b = (byte) 0xFC; // 0xFC = 1111 1100(补码)
  2. System.out.println(b); // 输出 -4(因为补码 1111 1100 表示 -4)
复制代码
(2)无符号转换

由于 Java 没有无符号 byte,需用 & 0xFF 转换:
  1. int unsignedValue = b & 0xFF; // 0xFC(252)
  2. System.out.println(unsignedValue); // 输出 252
复制代码
(3)网络协议 & 文件解析

<ul>读取 TCP/IP 报文、二进制文件时,数据可能是补码形式,需按补码解析:[code]// 从文件读取 2 字节的 short(补码存储)short value = (short) ((bytes[0]
您需要登录后才可以回帖 登录 | 立即注册