数的机器码表示(原码 反码 补码 移码)

本文详细介绍了真值与机器码的概念,并深入探讨了原码、反码、补码及移码四种不同的编码方式。每种编码的特点、表示方法及其在实际计算中的应用均有所涉及。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

首先区分两个概念:真值机器码

  • 真值:一般书写的数
  • 机器码:机器中表示的数

为了解决在计算机内部数的正、负符号和小数点运算问题,而产生了把符号位和数值位一起编码来表示相应的数的表示方法,如原码,反码,补码,移码

1.原码
  • 表示方法:符号位 + 二进制数的绝对值
  • 符号位:0为正,1为负,有+0-0之分
正数:0+二进制数
负数:1+二进制数
  • 特点:表示简单,易于同真值之间进行转换,实现乘除运算规则简单。但进行减运算十分麻烦
  • 例子:3的二进制数是11,则+3的原码是011,-3的原码是111
  • 使用原码做减法(11=01−1=0)
    11=1+(1)=[00000001]+[10000001]=[10000010]=21−1=1+(−1)=[00000001]原+[10000001]原=[10000010]原=−2
    结果错误
2.反码
  • 表示方法:正数的表示与原、补码相同. 负数的反码符号位为1,数值位是将原码的数值按位取反,就得到该数的反码表示。
  • 符号位:0为正,1为负,有+0-0之分
正数:0+二进制数
负数:1+二进制数按位取反
  • 特点:为求补码提供便利
  • 例子:3的二进制数是11,则+3的反码是011,-3的反码是100
  • 使用反码做减法(11=01−1=0)
    11=1+(1)=[00000001]+[10000001]=[00000001]+[11111110]=[11111111]=[10000000]=01−1=1+(−1)=[00000001]原+[10000001]原=[00000001]反+[11111110]反=[11111111]反=[10000000]原=−0
    结果正确,但出现了-0,这里的-0和+0是没有区别的,所以在这里让0带符号是没有意义的(数学上有时候需要带符号的0,但这里确实不需要,而且会使得对于同一个数有两种编码方式)
3.补码
  • 表示方法:正数的补码符号位为0 ,尾数与原码相同. 负数的补码符号位为1,数值位是将原码的数值按位取反,再在末位加1
  • 符号位:0为正,1为负,无+0-0之分
正数:0+二进制数
负数:1+(二进制数按位取反,末位+1)
  • 特点:将减法转化为加法
  • 例子:3的二进制数是11,则+3的补码是011,-3的补码是101
  • 使用补码做减法
    • 11=01−1=0
      11=1+(1)=[00000001]+[10000001]=[00000001]+[11111111]=[00000000]=[00000000]1−1=1+(−1)=[00000001]原+[10000001]原=[00000001]补+[11111111]补=[00000000]补=[00000000]原
      结果正确,且没有出现-0,这里是正负相加的结果,那如果是通过正正相加或者负负相加得到[10000000][10000000]补,又意味着什么呢?
    • 正正相加:(271)+1=12827−1)+1=128正溢
      (271)+1==[01111111]+[00000001]=[01111111]+[00000001]=[10000000]=[10000000](27−1)+1==[01111111]原+[00000001]原=[01111111]补+[00000001]补=[10000000]补=[10000000]原
      这里可以看到,用补码时,[10000000][10000000]原表示上溢的结果
    • 负负相加:26+(26)=128−26+(−26)=−128负溢
      26+(26)==[11000000]+[11000000]=[11000000]+[11000000]=[10000000]=[10000000]−26+(−26)==[11000000]原+[11000000]原=[11000000]补+[11000000]补=[10000000]补=[10000000]原
      这里可以看到,用补码时,[10000000][10000000]原也可以表示下溢的结果

在定点整数机器中,数的表示范围为|x|<(2n1)|x|<(2n−1),但n位二进制补码数的表示范围是2n1−2n−12n112n−1−1,
其中用[10000000][10000000]原来表示2n1−2n−1,这样不仅仅修复了0的符号以及存在两个编码的问题, 而且还能够多表示一个最低数. 这就是为什么8位二进制, 使用原码或反码表示的范围为[-127, +127], 而使用补码表示的范围为[-128, 127].
但是,同时要注意,用补码表示的2n1−2n−1是没有对应的反码和原码的,因为实际上是使用以前的-0的补码来表示-128

4.移码
  • 表示方法:移码和补码尾数相同,符号位相反
  • 符号位:1为正,0为负(注意,移码的符号表示与其他三种都不一样)
正数:1+二进制数
负数:0+(二进制数按位取反,末位+1)
  • 特点:通常用于表示浮点数的阶码
  • 例子:3的二进制数是11,则+3的移码是111,-3的移码是001

比较

表示方法正数负数+1011111-1011111
原码0+二进制数1+二进制数0101111111011111
反码0+二进制数1+二进制数按位取反0101111110100000
补码0+二进制数1+(二进制数按位取反,末位+1)0101111110100001
移码1+二进制数0+(二进制数按位取反,末位+1)1101111100100001
### 原码反码补码移码的定义 #### 定义说明 原码是一种最简单的二进制表示方法,其特点是符号位明确区分正负。对于正,符号位为`0`,值部分直接用二进制表示;而对于负,符号位为`1`,值部分同样保持不变[^3]。 反码是对原码的一种转换形式。对于正而言,反码与其原码完全一致;而针对负,则需将其值部分按位取反得到反码[^2]。 补码进一步改进了反码的形式,在处理负时更加高效。具体来说,正补码即为其本身,而负补码可通过对其反码加一获得。 移码主要用于浮点中的阶码表示,它通过将真值加上一个偏置量来实现无符号化存储。通常情况下,该偏置量等于\(2^{n-1}\),其中\(n\)代表总位。 --- ### 值范围分析 #### 原码值范围 假设机器字长为 \( n \) 位(含一位符号位),则: - 正的最大值为 \( (2^{n-1} - 1)_\text{十进制} \) - 负的最小值为 \( -(2^{n-1} - 1)_\text{十进制} \) 因此,原码能够表示的整范围为:\[ -(2^{n-1}-1) \sim +(2^{n-1}-1) \][^3] 值得注意的是,存在两个零值分别对应于 `+0` 和 `-0` 的不同编码方式。 #### 反码值范围 同理,当考虑 \( n \)-bit 字长时, - 对应正最大仍可达至 \(+(2^{n-1}-1)\), - 针对负情况亦可低达 \(-(2^{n-1}-1)\). 所以反码所能覆盖的整体区间同样是:\[-(2^{n-1}-1),+(2^{n-1}-1)\]. 同样地,这里也存在着两种不同的零表达形式(+0,-0)[^4]. #### 补码值范围 利用补码体系下, - 最大正值依旧维持在 \(+(2^{n-1}-1)\); - 不过由于引入了一种额外状态用于填原本由单独 "-0" 占据的位置,使得现在可以达到更低限度直到 \(-2^{n-1}\). 最终得出结论:采用这种机制之后整个可用空间变为连续闭合区域:[\-2^(n−1)..2^(n−1)1],并且解决了关于双重零表述的问题.[^4] #### 移码值范围 考虑到移码实际上是基于补码基础上增加固定偏移量的结果,故此如果原始补码支持从-\(2^{n-1}\)到+\((2^{n-1}-1)\)之间变化的话,那么相应调整后的实际显示效果就会是从0一直到\(2^n-1\). 这意味着每一个可能产生的组合都被赋予了一个独一无二非重复性的呈现形态. 综上所述,给定任意长度N比特的情况下,我们有如下关系成立: \[ [-(2^{n-1})..(2^{n-1}-1)]_{补码} → [(0)..(2^n-1)]_{移码}. \] --- ```python def range_summary(n_bits): max_positive = (2 ** (n_bits - 1)) - 1 min_negative_original_complement = -(2 ** (n_bits - 1)) result = { 'Original Code': f'{-max_positive} to {max_positive}', 'Complementary Code': f'{min_negative_original_complement} to {max_positive}', 'Offset Binary': f'{abs(min_negative_original_complement)} to {(2**n_bits)-1}' } return result print(range_summary(8)) ``` 上述代码展示了如何根据不同编码方案计算并总结它们各自的值范围。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值