数的机器码表示——彻底弄清什么是原码、反码、补码、移码

摘要:
数的机器码表示@目录数的机器码表示原码定点整数定点小数原码的计算反码定点整数定点小数反码的运算补码补码的由来定点整数定点小数补码的运算移码移码的表示移码的特点原码、反码、补码、移码为了妥善的处理数据运算过程中符号位的问题,于是就产生了把符号位和数值位一起编码起来表示相应的数的各种表示方法。例如我们熟悉的原码、反码、补码、移码等。通常将未经编码的数称为真值,编码后的数称为机器数或者机器码。

数的机器码表示

@

目录

为了妥善的处理数据运算过程中符号位的问题,于是就产生了把符号位和数值位一起编码起来表示相应的数的各种表示方法。例如我们熟悉的原码、反码、补码、移码等。通常将未经编码的数称为真值,编码后的数称为机器数或者机器码
  • 真值的形式正、负号加某进制数绝对值的形式,即数的实际值。如+3-5

  • 机器数的形式:真值按某种编码方式进行编码后的数值,即真值在机器中的表示,称为机器数,一般可以分为 无符号数和有符号数两种如:X=01011Y=11011

原码

定点整数

若定点整数的原码形式位(x_n x_{n-1}cdotcdotcdot x_1x_0),其中(x_n)为符号位,则原码表示的定义为:

[x_{[原]}=left{egin{matrix} x & 0 leqslant x<2^n \ 2^n-x=2^n+|x| & -2^n<xleqslant0 end{matrix} ight. ]

在上式中,x代表的是真值。

例如,(x=+7),化为二进制表示为(x=+0111);(x_{[原]}=0111)

(x=-7),化为二进制表示为(x=-0111);(x_{[原]}=2^3-(-0111)=1000+0111=1111)

我们可以总结出来:

  • 对于正数(x=+x_{n-1}...x_1x_0),它的原码是它自己本身,常常在最高位前面补0,代表它是一个正数。

    • (x_{[原]}=0x_{n-1}...x_1x_0)
  • 对于0,根据原码的定义则有两种表示形式:

    • (+0=+0_{n-1}...0_10_0)
      • 此时正0的原码为(+0_{[原]}=00_{n-1}...0_10_0)
    • (-0=-0_{n-1}...0_10_0)
      • 此时负0的原码为(-0_{[原]}=10_{n-1}...0_10_0)
  • 对于负数(x=-x_{n-1}...x_1x_0),它的原码是在最高位前面补1,代表它是一个负数。

    • (x_{[原]}=-x_{n-1}...x_1x_0)

对于一个定点整数原码(x_nx_{n-1}...x_1x_0),最高位(x_n)代表符号位,用0来表示正数,用1来表示负数。而(x_{n-1}...x_1x_0)则代表的是数值位。它的大小就是该原码对应真值的绝对值。

我们很容易求出它的范围([-(2^n-1),2^n-1])

定点小数

假设定点小数的原码形式为(x_s.x_1x_2...x_n)(实际上小数点是不存储的),其中(x_s)代表符号位。则原码的定义为:

[x_{[原]}=left{egin{matrix}x & 0 leqslant x<1 \ 1-x=1+|x| & -1<xleqslant0end{matrix} ight. ]

在上式中,x代表的是真值。

例如,(x=+0.875),化为二进制表示为(x=+0.111);(x_{[原]}=0.111)

(x=-0.875)二进制表示为(x=-0.111);(x_{[原]}=1.000-(-0.111)=1.000+0.111=1.111)。 我们可以总结出来:

  • 对于正数(x=+0.x_{n-1}...x_1x_0),它的原码是它自己本身,常常在最高位前面补0,代表它是一个正数。(注意,前面的0.实际上是不存储的,也就是实际最高位是(x_{n-1}))

    • (x_{[原]}=0.x_{n-1}...x_1x_0)
  • 对于0,根据原码的定义则有两种表示形式:

    • (+0=+0.0_{n-1}...0_10_0)
      • 此时正0的原码为(+0_{[原]}=0.0_{n-1}...0_10_0)
    • (-0=-0.0_{n-1}...0_10_0)
      • 此时负0的原码为(-0_{[原]}=1.0_{n-1}...0_10_0)
  • 对于负数(x=-0.x_{n-1}...x_1x_0),它的原码是在最高位前面补1,代表它是一个负数。(注意,前面的0.实际上是不存储的,也就是实际最高位是(x_{n-1}))

    • (x_{[原]}=-1.x_{n-1}...x_1x_0)

对于一个定点小数原码 (x_s.x_1x_2...x_n),最高位 (x_s)代表符号位,用0来表示正数,用1来表示负数。而(x_1x_2...x_n)则代表的是数值位。它的大小就是该原码对应真值的绝对值。

我们很容易求出它的范围[(2^{-n}-1,1-2^{-n})]

原码的计算

​ 原码虽然表示极为简单,但是最大的问题就是加法运算十分复杂

两数相加时,我们需要考虑两个数的符号,如果符号相同,我们可以把数值位直接相加,然后在最高位前边添加上原来的符号位。但如果符号位不相同,那么我们就要考虑进行减法运算。进行减法的时候,我们需要考虑数值位的绝对值大小来决定符号位。这也就是原码运算的缺点:参与运算复杂,需要将数值位与符号位分开考虑。

反码

当进行减法的时候,人们想到如何把减法变为加法,那么这样会更加简便,只靠加法器就可以完成运算。比如

(1-1=0)

(0001-0001=0000)

(1+(-1)=0)

(0001+1001=1010=-2)

显然是计算错误的。

于是人们引入了反码来表示负数。

定点整数

设定点整数的反码形式为(x_n x_{n-1}cdotcdotcdot x_1x_0)(x_n)代表符号位。

[x_{[反]}=left{egin{matrix}x & 0 leqslant x<2^n-1 \ 2^{n}-1+x=2^n-1-|x| & -(2^n-1) < xleqslant0end{matrix} ight. ]

对于正数,它的反码为它本身,如+7=0111,它的反码为0111

对于负数,它的反码表示为:符号位不变,数值位取反。,如-7=1000

对于0

  • +0
    • 0000-->0000
  • -0
    • 1000-->1111

定点小数

假设定点小数的反码形式为(x_s.x_1x_2...x_n)(实际上小数点是不存储的),其中(x_s)代表符号位。则反码的定义为:

[x_{[反]}=left{egin{matrix}x & 0 leqslant x<1 \ 2-2^{-n}+x=2-2^{-n}-|x| & -1<xleqslant0end{matrix} ight. ]

在上式中,x代表的是真值。

反码的运算

注:如果最高位相加后产生进位,则最后得到的结果要加1。

(1+(-1)=0)

0001+1110=1111=-0

在以-126+127=1为例

10000001+01111111=100000000

  • 进了一位,末位加一
    • 10000000+01111111+1
    • 最后结果为00000001

也就是说,反码解决了把减法化为加法的问题。

补码

补码的由来

为了解决原码的计算问题,人们引入了补码

我们先从时钟的例子来介绍补码的原理。

比如我们将定在五点的钟表跳到三点,有2种调法:

image-20200318143453928image-20200318143525840

我们既可以顺时针调也可以逆时针调。也就是说我们(5-2)(5+10)的效果是一样的。

而把这种思想引入到计算机中,不就可以把减法转为加法了吗?

[5-2=5+10(MOD 12) \5+(-2)=5+10(MOD 12)\ -2=10(MOD 12) ]

在上面的式子中,在模为12的情况下,-2的补码就是10。一个负 数用其补码代替,同样可以得到正确的运算结果。

那什么是呢?

计算机中运算器、寄存器、计数器都有一定的位数,不可能容纳无限大的任意数。当运算结果超出实际的最大表示范围, 就会发生溢出,此时所产生的溢出量就是模(module)

可以把模定义为一个计量器的容量

如一个八位计数器0000 0000~1111 1111,它表示的范围就是[0,255]。当计数器表示为1111 1111 时,如果计数器再加一,那么此计数器就会溢出。计数器上的数值会变成0000 0000.而此计数器的溢出量就是256.

假设此计数器表示一个定点小数,它表示的范围就是[0,2-(2^{-8})]。当表示最大的时候,计数器值为1.111 1111计数器加一的时候,那么计数器就会清零,变为0.0000000。那么此此定点小数的溢出量就是2.

从上面我们可以推导出,一个n+1位定点整数(x_n x_{(n-1)} ... x_2 x_1 x_0),它的溢出量为(2^{n+1}),所以模为(2^{n+1})

任意一个定点小数(x_s.x_1x_2...x_n),它的溢出量是2,所以模为2。

在计算机中,机器能表示的数据位数是固定的, 其运算都是有模运算。若运算结果超出了计算机所能表示的数值范围, 则只保留它的小于模的低n+1位的数值,超过n+1 位的高位部分就自动舍弃了。

下面我们来引入补码的定义

定点整数

定点整数的补码形式为(x_n x_{n-1}cdotcdotcdot x_1x_0),其中(x_n)为符号位,补码表示的定义为:

[x_{[补]}=left{egin{matrix}x & 0 leqslant x<2^n \ 2^{n+1}+x=2^{n+1}-|x| & -2^n leqslant xleqslant0end{matrix} ight. ]

在上式中,x代表的是真值

例如,(x=+7),化为二进制表示为(x=+0111);(x_{[补]}=0111)

(x=-7),化为二进制表示为(x=-0111);(x_{[补]}=2^4+(-0111)=10000-0111=1001)

我们可以总结出来:

  • 对于正数(x=+x_{n-1}...x_1x_0),它的补码是它自己本身,常常在最高位前面补0,代表它是一个正数。

  • (x_{[补]}=0_nx_{n-1}...x_1x_0)

  • 对于0,根据补码的定义:

    • (+0=+0_{n-1}...0_10_0)

      • 此时正0的补码为(+0_{[补]}=0_n0_{n-1}...0_10_0)
    • (-0=-0_{n-1}...0_10_0)

      • 此时负0的补码为(-0_{[补]}=(10_n0_{n-1}...0_10_0-0_{n-1}...0_20_10_1)mod(10_n0_{n-1}...0_10_0)=0_n0_{n-1}...0_10_0)

      由此可见,零的补码是唯一的,没有+0和-0之分。

  • 对于负数(x=-x_{n-1}...x_1x_0)

    ​ 常常可以通过把数值位按位取反,然后末位加一来计算负数的补码

    • 如求(-127)的补码
      • $[-0111 1111]_{[补]}=10000 0000-01111111 $
      • (10000000=11111111+1)
      • ([-0111 1111]_{[补]}=11111111-01111111+1),这一步刚刚说明了上面的计算方法的原理。

    (-128)的补码的求法。

    • -128=-1000 0000
    • ([-10000000]_{[补]}=11111111-10000000+1=10000000)

    其实还有一个更为渐变的补码的求法:从右到左遇到第一个 1 的前面各位取反。也就是从右向左,遇到1之前,还保持原样。遇到1之后,各位取反。以-126为例:(-126=-01111110)

    [-01111110]的补码位10000010,10是不变的。而黑体部分则是取反的。

对于补码的取值范围,10000000-11111111——- (-128)~(-1)

00000000~011111111 ——0~127

推广到n位数,则补码的范围就是[(-2^{n-1},2^{n-1}-1)]

定点小数

定点小数的补码形式为(x_s.x_1x_2...x_n)(实际上小数点是不存储的),其中(x_s)代表符号位。则补码的定义为:

[x_{[原]}=left{egin{matrix}x & 0 leqslant x<1 \ 2+x=2-|x| & -1leqslant xleqslant0end{matrix} ight. ]

在上式中,x代表的是真值。

例如,(x=+0.875),化为二进制表示为(x=+0.111);(x_{[补]}=0.111)

(x=-0.875)二进制表示为(x=-0.111);(x_{[补]}=10.000-(0.111)=1.001)

我们可以总结出来:

  • 对于正数(x=+0.x_{n-1}...x_1x_0),它的补码是它自己本身,常常在最高位前面补0,代表它是一个正数。(注意,前面的0.实际上是不存储的,也就是实际最高位是(x_{n-1}))

  • (x_{[原]}=0.x_{n-1}...x_1x_0)

  • 对于0,根据补码的定义:

    • (+0=+0.0_{n-1}...0_10_0)

      • 此时正0的补码为(+0_{[补]}=0.0_{n-1}...0_10_0)
    • (-0=-0.0_{n-1}...0_10_0)

      • 此时负0的补码为(-0_{[补]}=(10.0_{n-1}...0_10_0-0.0_{n-1}...0_10_0)mod(10.0_{n-1}...0_10_0)=0.0_{n-1}...0_10_0)

      也就是说,0的补码是唯一的

  • 对于负数

    按位取反,末位加一,和定点整数一样。虽然我们看起来有一个小数点,但是实际上小数点是不存储的。

定点小数的补码的范围,0000~0111--> [0,0.875]

1000~1111--> [-1,-0.125]

扩展到n位补码

我们很容易求出它的范围$[-1,1-2^{-(n-1)}] $

补码的运算

假设一个二进制整数补码有n+1位,(x_nx_{n-1}...x_2x_1x_0),则补码与真值的对应关系可以这么表示:

(X_{真值}=-2^n imes x_n+sum_{0}^{n-1}2^ix_n)

当该数为正整数的时候,(x_n)位变为0,(0x_{n-1}...x_2x_1x_0),

(X_{真值}=sum_{0}^{n-1}2^ix_n)

当该数为负整数的时候,(x_n)位变为1,(1 x_{n-1}...x_2x_1x_0),

(X_{真值}=-2^n+sum_{0}^{n-1}2^ix_n)

  • 以-127为例,-127=-01111111
    • 它的补码为10000001
    • 从补码求真值的过程:-10000000+1=-01111111-1+1=-01111111

上面我们说到过,计算机中用原码进行加减运算是十分麻烦的,那么我们来看一下用补码来运算。

(126-127=0)

  • 原码

    • (01111110-01111111)

    • 我们需要比较数值位的绝对值大小,来决定符号位,1

    • 1111111-1111110=0000001

    • 10000001

      假设把减法看成加法

      • 01111110+(-01111111)=01111110+11111111=100000001
      • 1会溢出,那么得到的结果就是00000001,按原码表示的化,真值为1,显然是错误的。
  • 补码

    • 01111110+10000001=11111111
    • 转换为真值后为-1。正确的
    • 原理是这样的
      • 126-127=-1
      • 126+(-127)=-1
      • 126+129mod256=-1
      • 这里-127等效于129mod256

由此,我们可以看出,补码实际上是可以直接带符号位运算的运算的。

求相反数的补码:由[X]补求[-X]补

带符号位一起取反,然后末位加一

如求我们已知+127的补码求-127的补码

  • 01111111
  • 10000001

移码

移码通常用于表示浮点数的阶码。由于阶码是k位的整数,假设定点整数移码形式为(e_ke_{k-1}...e_2e_1e_0)最高位为符号位是。移码的传统定义是:

([e]_移=2^k+e)

上式中,e为真值,(2^k)为固定的偏移值常数。

与[x]补的区别:符号位相反

真值补码移码
-810000000
-710010001
-610020002
……............
000001000
+100011001
…….............
+701111111

移码的表示

移码表示的机器数为数的真值在数轴上向右平移了 固定的偏移值。

如八位移码:

image-20200319141504001

移码的特点

  • 在移码中,最高位为0表示负数,最高位为1表示正数,这与原 码、补码、反码的符号位取值正好相反
  • 移码为全0时所对应的真值最小,为全1时所对应的真值最大! 因此,移码的大小直观地反映了真值的大小,这将有助于两个 浮点数进行阶码大小比较
  • 真值0在移码中的表示形式是唯一的,即:[+0]移= [0]移= 100…00
  • 移码把真值映射到一个正数域,所以可将移码视为无符号数, 直接按无符号数规则比较大小。
  • 同一数值的移码和补码除最高位相反外,其他各位相同。

原码、反码、补码、移码

取值范围的一个比较

数的机器码表示——彻底弄清什么是原码、反码、补码、移码第4张

免责声明:文章转载自《数的机器码表示——彻底弄清什么是原码、反码、补码、移码》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Cassandra开发入门文档第四部分(集合类型、元组类型、时间序列、计数列)erlang接入远程shell下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

计算机基础知识:原码、反码、补码

可能很多人有这样的疑问,我们为什么要了解原码、反码、补码,它能帮助我们解决什么问题?在编写代码中有什么实际用途呢? 我是这样认为的,其一,作为计算机基础知识,我们必须有所了解。其二、这些基础知识无论是普通的编写代码,还是研究高超的算法都离不开它。 例:我们常见的位运算 按位与(&)、按位或(|)、取反(~)等等。 在代码中, 我们可能经常会碰到这样...

C/C++(基础编码-补码详解)

两个数的交换 1.引入第三者。 2.求和运算,求差。(这样会产生内存溢出) 3.异或运算 a = a^b; b = a^b; a = a^b; 8b(bit位) = 1B(Byte=字节)//最小单位是字节 32位机:2^32 = 4G寻址能力 (王爽--统一编址,汇编语言) char类型一个字节,8位。[-128,12...

原码,反码,补码详解

本篇文章讲解了计算机的原码, 反码和补码. 并且进行了深入探求了为何要使用反码和补码, 以及更进一步的论证了为何可以用反码, 补码的加法计算原码的减法. 论证部分如有不对的地方请各位牛人帮忙指正! 希望本文对大家学习计算机基础有所帮助! 一. 机器数和真值 在学习原码, 反码和补码之前, 需要先了解机器数和真值的概念. 1、机器数 一个数在计算机中的二进制...

DBC的故事(二)

上篇介绍了MSB和LSB,此篇介绍更复杂的:有符号和无符号数。 1.信号符号 CAN信号有其物理意义,如温度、扭矩等,这些信号是有负值的,常见的解决方案有2种: 1)把offset设成负值 如温度offset=-40,则温度最小值-40。 2)CAN信号类型设为有符号 上篇文章中提到signal定义中有SignedFlag,当SignedFlag是负号时,...

原码反码补码

原码反码补码 (1)原码表示法原码表示法是机器数的一种简单的表示法。其符号位用0表示正号,用:表示负号,数值一般用二进制形式表示。设有一数为x,则原码表示可记作〔x〕原。例如,X1= +1010110X2= 一1001010其原码记作:〔X1〕原=[+1010110]原=01010110〔X2〕原=[-1001010]原=11001010原码表示数的范围与...

004_详解计算机各种语言浮点数运算会存在精度损失原因

      数值数据是一种带符号数,有正负之分.在计算机中对数据进行运算操作时,符号位如何表示?是否也同数值位一道参加运算?如参加,会给运算操作带来什么影响?为了妥善处理好这些问题,就产生了将数值位连同符号位一起编码来表示相应的数的各种表示方法,如数据的原码、补码、反码和移码表示法. 一、所有相关的码解释 (1)正数的原码=反码=补码 负数原码=>最...