补码 订阅
计算机中的有符号数有三种表示方法,即原码、反码和补码。三种表示方法均有符号位和数值位两部分,符号位都是用0表示“正”,用1表示“负”,而数值位,三种表示方法各不相同 [1]  。在计算机系统中,数值一律用补码来表示和存储。原因在于,使用补码,可以将符号位和数值域统一处理;同时,加法和减法也可以统一处理 [2]  。 展开全文
计算机中的有符号数有三种表示方法,即原码、反码和补码。三种表示方法均有符号位和数值位两部分,符号位都是用0表示“正”,用1表示“负”,而数值位,三种表示方法各不相同 [1]  。在计算机系统中,数值一律用补码来表示和存储。原因在于,使用补码,可以将符号位和数值域统一处理;同时,加法和减法也可以统一处理 [2]  。
信息
外文名
two's complement representation
作    用
存储数值
所属领域
计算机
中文名
补码
补码概念引入
在介绍补码概念之前,先介绍一下“模”的概念:“模”是指一个计量系统的计数范围,如过去计量粮食用的斗、时钟等。计算机也可以看成一个计量机器,因为计算机的字长是定长的,即存储和处理的位数是有限的,因此它也有一个计量范围,即都存在一个“模”。如:时钟的计量范围是0~11,模=12。表示n位的计算机计量范围是 ,模= .“模”实质上是计量器产生“溢出”的量,它的值在计量器上表示不出来,计量器上只能表示出模的余数。任何有模的计量器,均可化减法为加法运算 [3]  。假设当前时针指向8点,而准确时间是6点,调整时间可有以下两种拨法:一种是倒拨2小时,即8-2=6;另一种是顺拨10小时,8+10=12+6=6,即8-2=8+10=8+12-2(mod 12).在12为模的系统里,加10和减2效果是一样的,因此凡是减2运算,都可以用加10来代替。若用一般公式可表示为:a-b=a-b+mod=a+mod-b。对“模”而言,2和10互为补数。实际上,以12为模的系统中,11和1,8和4,9和3,7和5,6和6都有这个特性,共同的特点是两者相加等于模。对于计算机,其概念和方法完全一样。n位计算机,设n=8,所能表示的最大数是11111111,若再加1成100000000(9位),但因只有8位,最高位1自然丢失。又回到了 00000000,所以8位二进制系统的模为 。在这样的系统中减法问题也可以化成加法问题,只需把减数用相应的补数表示就可以了。把补数用到计算机对数的处理上,就是补码 [3]  。
收起全文
精华内容
下载资源
问答
  • C++ 补码详解

    万次阅读 2020-12-07 19:37:06
    计算机补码详解

    一、引例

    	printf("%d\n", abs(INT_MIN));
    
    • 这段的代码正确输出应该是什么呢?
    • 凭直觉肯定是个正数,因为 abs 这个函数是求一个数的绝对值,数学上任何数的绝对值都是大于等于0的;然而…

    -2147483648

    • 那么我们来研究一下,计算机背后到底做了什么手脚;

    二、机器数和真值

    1、机器数

    • 我们知道计算机是内部由 0 和 1 组成的编码,无论是整数还是浮点数,都会涉及到负数,对于机器来说是不知道正负的,而 “正” 和 “负” 正好是两种对立的状态,所以规定用 “0” 表示 “正”,“1” 表示 “负”,这样符号就被数字化了,并且将它放在有效数字的前面,就成了有符号数;
    • 把符号 “数字化” 的数称为 机器数

    2、真值

    • 而带有 “+” 或者 “-” 的数称为 真值
    • 然而,当符号位和数值部分放在一起后,如何让它一起参与运算呢?那就要涉及到接下来要讲的计算机的各种编码了;

    三、计算机编码

    1、原码

    • 这里的原码并不是源码(源代码)的意思,而是机器数中最简单的一种表示形式;为了快速理解,这里只介绍整数,不介绍小数的情况;

    【原码定义】 符号位为 0 代表正数,符号位为 1 代表负数,数值位为真值的绝对值。

    [x]={x(0<=x<2n1)2n1x(2n1<x<=0) [x]_原 = \begin{cases} x & (0 <= x < 2^{n-1})\\ 2^{n-1} - x & (-2^{n-1} < x <= 0)\\ \end{cases}
    (这里 nn 的取值是 81632648、16、32、64,目前计算机的整型 int 都是 32 位的,但是为了便于阅读,本文介绍的整数都按照 8 位来举例)

    【原码举例】

    • 1)当真值 x = +100101 时,原码为:00100101;

    • 2)当真值 x = -100101 时,原码为:10100101;

    • 原码是最贴近人类的编码方式,并且很容易和真值进行转换,但是让计算机用原码进行加减运算过于繁琐,如果两个数符号位不同,需要先判断绝对值大小,然后用绝对值大的减去绝对值小的,并且符号以绝对值大的数为准,本来是加法却需要用减法来实现;为了让计算机做的事情尽量简单,于是设计出来了补码;

    2、补码

    【补码定义】 正数的补码是它本身,符号位为0;负数的补码为原码数值位取反后+1,符号位为1;
    [x]={x(0<=x<2n1)2n+x(2n1<=x<0) [x]_补 = \begin{cases} x & (0 <= x < 2^{n-1})\\ 2^{n} + x & (-2^{n-1} <= x < 0)\\ \end{cases}
    【补码举例】

    • 1)当真值 x = +100101 时,补码为:00100101;
    • 2)当真值 x = -100101 时, 补码为:11011011;

    (尝试把负数的数值部分和它的补码进行相加运算,可以得到 2n2^n

    3、反码

    • 反码一般用来作为 补码 求 原码 或者 原码 求 补码 的中间过渡;

    【反码定义】 整数的反码是它本身,符号位为0;负数的反码为原码数值取反,符号位为1;
    [x]={x(0<=x<2n1)2n1+x(2n1<x<=0) [x]_反 = \begin{cases} x & (0 <= x < 2^{n-1})\\ 2^{n}-1 + x & (-2^{n-1} < x <= 0)\\ \end{cases}
    【反码举例】

    • 1)当真值 x = +100101 时,补码为:00100101;
    • 2)当真值 x = -100101 时, 补码为:11011010;

    (尝试把负数的数值部分和它的补码进行相加运算,可以得到 2n12^n-1

    4、编码总结

    • 1)这三种机器数的最高位均为符号位;
    • 2)当真值为正数时,原码、补码、反码的表示形式相同,符号位用 “0” 表示,数值部分真值相同;

    [+1]=[00000001]=[00000001]=[00000001][+1] = [00000001]_原 = [00000001]_反 = [00000001]_补

    • 3)当真值为负数时,原码、补码、反码的表示形式不同,但是符号位都用 “1” 表示,数值部分:反码是原码的 “每位求反”,补码是原码的 “取反加1”;

    [1]=[10000001]=[11111110]=[11111111][-1] = [10000001]原 = [11111110]反 = [11111111]补

    四、为什么要用补码

    1、主要目的

    • 计算机的四则运算希望设计的尽量简单。但是引入符号位的概念,对于计算机来说还要考虑正负数相加,等于引入了减法,所以希望是计算机底层只设计一个加法器,就能把加法和减法都做了。

    2、原码运算

    • 对于原码的加法,两个正数相加的情况如下:

    1+1=[00000001]+[00000001]=[00000010]1 + 1 = [00000001]_原 + [00000001]_原 = [00000010]_原 = 2

    • 好像没有什么问题?于是人们开始探索减法,但是起初设计的人的初衷是希望不用减法,只用加法运算就能够将加法和减法都包含进来,于是,我们尝试用原码的负数表示来做运算;

    12=1+(2)=[00000001]+[10000010]=[10000011]1 - 2 = 1 + (-2) = [00000001]_原 + [10000010]_原 = [10000011]_原 = -3

    • 这个结果是错的,于是为了解决减法问题,引入了反码运算;

    3、反码运算

    • 对于反码的加法,一正一负两数相加的情况如下:

    12=1+(2)=[00000001]+[11111101]=[11111110]1 - 2 = 1 + (-2) = [00000001]_反 + [11111101]_反 = [11111110]_反 = -1

    • 没有什么问题?但是某种情况下,反码会有歧义,当两个相同的数相减时,如下:

    11=1+(1)=[00000001]+[11111110]=[11111111]1 - 1 = 1 + (-1) = [00000001]_反 + [11111110]_反 = [11111111]_反 = -0

    • 这里出现了一个奇怪的概念,就是 “负零”,反码运算过程中会出现有两个编码表示零这个数值;
    • 为了解决正负零的问题引入了补码的概念;

    4、补码运算

    • 1)一正一负两个数相加,且非零的情况:

    12=1+(2)=[00000001]+[11111110]=[11111111]1 - 2 = 1 + (-2) = [00000001]_补 + [11111110]_补 = [11111111]_补 = -1

    • 2)一正一负两个数相加,且答案为零的情况:

    11=1+(1)=[00000001]+[11111111]=[00000000]1 - 1 = 1 + (-1) = [00000001]_补 + [11111111]_补 = [00000000]_补 = 0

    两个互为相反数的数相加后,得到的数的补码为 2n2^n(你可以认为是是溢出了),和我们之前提到的定义吻合;

    • 综上所述,计算机内部都是用补码表示;

    五、回到原点

    • 最后我来回答下,文章一开始提到的那个问题,即为什么一个负数的绝对值还是一个负数;
    • 这个负数不是一个一般的负数,它是32位有符号整型的最小值,即:
      INT_MIN=231INT\_MIN = -2^{31}
    • 它的补码表示为:
      [231]=[10000000  00000000  00000000  00000000][-2^{31}]_补 = [10000000\ \ 00000000\ \ 00000000\ \ 00000000]_补
    • 从补码的定义出发:
      [x]={x(0<=x<231)232+x(231<=x<0) [x]_补 = \begin{cases} x & (0 <= x < 2^{31})\\ 2^{32} + x & (-2^{31} <= x < 0)\\ \end{cases}

    231231=231+(231)=X+[231]=02^{31} - 2^{31} = 2^{31} + (- 2^{31}) = X + [-2^{31}]_补 = 0

    解这个简单方程得到 XX 唯一的值为:
    [10000000  00000000  00000000  00000000][10000000\ \ 00000000\ \ 00000000\ \ 00000000]_补

    • 所以在 32位有符号整数体系内, INT_MIN=INT_MININT\_MIN = -INT\_MIN
    展开全文
  • 补码

    2020-01-28 15:53:01
    补码 计算机中的有符号数有三种表示方法,即原码、反码和补码。三种表示方法均有符号位和数值位两部分,符号位的表示,0表示“正”,1表示“负”,而数值位,就是0和1的组合。 在计算机系统中,数值一律用补码来表示...

    补码

    计算机中的有符号数有三种表示方法,即原码、反码和补码。三种表示方法均有符号位和数值位两部分,符号位的表示,0表示“正”,1表示“负”,而数值位,就是0和1的组合。

    在计算机系统中,数值一律用补码来表示和存储。原因在于,使用补码,可以将符号位和数值域统一处理;同时,加法和减法也可以统一处理 。

    补码的优点:

    (1)解决了符号的表示问题;
    (2)可以将减法运算转化为补码的加法运算来实现,克服了原码加减法运算繁杂的弊端,可有效简化运算器的设计;
    (3)在计算机中,利用电子器件的特点实现补码和真值、原码之间的相互转换,非常容易;
    (4)补码表示统一了符号位和数值位,使得符号位可以和数值位一起直接参与运算。

    展开全文

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 19,556
精华内容 7,822
关键字:

补码