机器数是计算机中用来表示数值的二进制形式

  1. 机器数的基本概念
    机器数是计算机中用来表示数值的二进制形式。其特点包括:
  • 使用二进制表示数据;
  • 符号用最高位表示:0 表示正数,1 表示负数;
  • 小数点为隐含表示(如定点整数或定点小数),不单独占用存储位。
    根据是否有符号位,可分为:
  • 无符号数:仅表示非负整数(从 0 到 2n−12^n - 12n1);
  • 带符号数:最高位为符号位,其余位表示数值大小。
  1. 原码编码规则
    原码是一种最直观的带符号数表示方法:
  • 正数:符号位为 0,数值部分为绝对值的二进制表示;
  • 负数:符号位为 1,数值部分仍为绝对值的二进制表示。

对于机器字长为 nnn 的情况:

  • 纯整数原码范围−(2n−1−1)-(2^{n-1} - 1)(2n11)+(2n−1−1)+(2^{n-1} - 1)+(2n11)
  • 纯小数原码(假设小数点在符号位后):数值 X 满足 −1<X<1-1 < X < 11<X<1,则:
    • 正数:[X]原=0.X1X2...Xn−1[X]_{\text{原}} = 0.X_1X_2...X_{n-1}[X]=0.X1X2...Xn1
    • 负数:[X]原=1.X1X2...Xn−1[X]_{\text{原}} = 1.X_1X_2...X_{n-1}[X]=1.X1X2...Xn1

特点

  • 简单直观,便于人理解;
  • “0”有两种表示
    • [+0]原=00000000[+0]_{\text{原}} = 00000000[+0]=00000000
    • [−0]原=10000000[-0]_{\text{原}} = 10000000[0]=10000000(以8位为例)
  • 运算复杂,需单独处理符号位和判断正负。
  1. 反码编码规则
    反码是对原码的一种改进,主要用于简化运算逻辑(尤其是在补码出现前)。
  • 正数:反码与原码相同;
  • 负数:符号位不变(为1),数值位按位取反。

数学表达式(字长为 nnn):

  • 整数反码
    • 正数:[X]反=X[X]_{\text{反}} = X[X]=X
    • 负数:[X]反=2n−1+X[X]_{\text{反}} = 2^n - 1 + X[X]=2n1+X (其中 XXX 为负整数)
  • 小数反码
    • 负数:[X]反=2−2−(n−1)+X[X]_{\text{反}} = 2 - 2^{-(n-1)} + X[X]=22(n1)+X

特点

  • 同样存在两种“0”的表示:
    • [+0]反=00000000[+0]_{\text{反}} = 00000000[+0]=00000000
    • [−0]反=11111111[-0]_{\text{反}} = 11111111[0]=11111111
  • 是原码向补码过渡的形式,在现代系统中已基本不用。
  1. 应用场景
  • 原码:用于理解符号数的基本概念,常用于教学场景;
  • 反码:历史上曾用于某些早期计算机系统,现主要用于帮助理解补码的构造过程;
  • 补码:当前几乎所有计算机系统都采用补码表示带符号整数,因为:
    • 统一了加减法运算(减法可转化为加法);
    • “0”有唯一表示;
    • 可多表示一个负数(如8位补码范围为 -128 ~ +127);
    • 硬件实现更高效。
# 示例:8位补码中 -1 的表示
def twos_complement(x, n=8):
    if x >= 0:
        return x
    else:
        return (1 << n) + x

print(bin(twos_complement(-1)))  # 输出: 0b11111111 (即 255)

补码通过统一模运算的数学结构,解决了原码和反码中“+0”与“−0”有两种不同编码的问题。

问题回顾:原码和反码中的“0的双重表示”

  • 原码 中:
    • [+0]原=00000000[+0]_{\text{原}} = 00000000[+0]=00000000
    • [−0]原=10000000[-0]_{\text{原}} = 10000000[0]=10000000(符号位为1,数值为0)
  • 反码 中:
    • [+0]反=00000000[+0]_{\text{反}} = 00000000[+0]=00000000
    • [−0]反=11111111[-0]_{\text{反}} = 11111111[0]=11111111(符号位为1,数值位全取反)

这导致系统需要额外判断两种“0”的情况,增加了硬件设计复杂性。


补码如何解决这个问题?

在补码表示中,负数是通过对正数取反加一得到的,其本质是基于模(modular arithmetic)运算:

以8位机器为例:
  • 总共有 28=2562^8 = 25628=256 个不同的二进制组合;
  • 补码将这些组合划分为:
    • 正数和0:0 ~ 127(即 0000000001111111
    • 负数:−128 ~ −1(即 1000000011111111

关键点:只有一个编码对应数值 0 —— 就是 00000000

数学原理:模 2n2^n2n 运算

对于一个 n 位二进制数,补码实际上是该数对 2n2^n2n 取模的结果。
例如,在8位系统中,任何运算都在 mod 256 下进行。

所以:

  • [−0]补=(28+(−0))mod  256=0[-0]_{\text{补}} = (2^8 + (-0)) \mod 256 = 0[0]=(28+(0))mod256=0
  • 即无论正负零,补码都等于 00000000

因此,−0 的补码与 +0 完全相同,实现了“0”的唯一表示。

示例:求 −0 的补码(8位)
n = 8
zero = 0
negative_zero_complement = (1 << n) + (-zero)  # 256 + 0 = 256 → mod 256 = 0
print(bin(negative_zero_complement % (1 << n)))  # 输出: 0b0 → 即 00000000

更进一步的优势

除了消除“0的双重表示”,补码还带来以下好处:

  1. 简化运算器设计:减法可以转化为加法(如 A−B=A+(−B)补A - B = A + (-B)_{\text{补}}AB=A+(B));
  2. 无需单独处理符号位:符号位参与运算;
  3. 范围更优:8位补码可表示 −128 到 +127,比原码多一个负数(−128);

✅ 结论:
补码通过模运算机制,使得 −0 和 +0 映射到同一个二进制编码 00000000,从而彻底解决了原码和反码中存在的“0的双重表示”问题,提高了运算效率和硬件实现的简洁性。
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Bol5261

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

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

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

打赏作者

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

抵扣说明:

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

余额充值