原码, 反码, 补码 详解

原码, 反码, 补码 详解

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

 

一. 机器数和真值

在学习原码, 反码和补码之前, 需要先了解机器数和真值的概念.

1、机器数

一个数在计算机中的二进制表示形式,  叫做这个数的机器数。机器数是带符号的,在计算机用一个数的最高位存放符号, 正数为0, 负数为1.

比如,十进制中的数 +3 ,计算机字长为8位,转换成二进制就是00000011。如果是 -3 ,就是 10000011 。

那么,这里的 00000011 和 10000011 就是机器数。

2、真值

因为第一位是符号位,所以机器数的形式值就不等于真正的数值。例如上面的有符号数 10000011,其最高位1代表负,其真正数值是 -3 而不是形式值131(10000011转换成十进制等于131)。所以,为区别起见,将带符号位的机器数对应的真正数值称为机器数的真值。

例:0000 0001的真值 = +000 0001 = +1,1000 0001的真值 = –000 0001 = –1

 

二. 原码, 反码, 补码的基础概念和计算方法.

在探求为何机器要使用补码之前, 让我们先了解原码, 反码和补码的概念.对于一个数, 计算机要使用一定的编码方式进行存储. 原码, 反码, 补码是机器存储一个具体数字的编码方式.

1. 原码

原码就是符号位加上真值的绝对值, 即用第一位表示符号, 其余位表示值. 比如如果是8位二进制:

[+1] = 0000 0001

[-1] = 1000 0001

第一位是符号位. 因为第一位是符号位, 所以8位二进制数的取值范围就是:

[1111 1111 , 0111 1111]

[-127 , 127]

原码是人脑最容易理解和计算的表示方式.

2. 反码

反码的表示方法是:

正数的反码是其本身

负数的反码是在其原码的基础上, 符号位不变,其余各个位取反.

[+1] = [00000001] = [00000001]

[-1] = [10000001] = [11111110]

可见如果一个反码表示的是负数, 人脑无法直观的看出来它的数值. 通常要将其转换成原码再计算.

3. 补码

补码的表示方法是:

正数的补码就是其本身

负数的补码是在其原码的基础上, 符号位不变, 其余各位取反, 最后+1. (即在反码的基础上+1)

[+1] = [00000001] = [00000001] = [00000001]

[-1] = [10000001] = [11111110] = [11111111]

对于负数, 补码表示方式也是人脑无法直观看出其数值的. 通常也需要转换成原码在计算其数值.

 

三. 为何要使用原码, 反码和补码

在开始深入学习前, 我的学习建议是先"死记硬背"上面的原码, 反码和补码的表示方式以及计算方法.

现在我们知道了计算机可以有三种编码方式表示一个数. 对于正数因为三种编码方式的结果都相同:

[+1] = [00000001] = [00000001] = [00000001]

所以不需要过多解释. 但是对于负数:

[-1] = [10000001] = [11111110] = [11111111]

可见原码, 反码和补码是完全不同的. 既然原码才是被人脑直接识别并用于计算表示方式, 为何还会有反码和补码呢?

首先, 因为人脑可以知道第一位是符号位, 在计算的时候我们会根据符号位, 选择对真值区域的加减. (真值的概念在本文最开头). 但是对于计算机, 加减乘数已经是最基础的运算, 要设计的尽量简单. 计算机辨别"符号位"显然会让计算机的基础电路设计变得十分复杂! 于是人们想出了将符号位也参与运算的方法. 我们知道, 根据运算法则减去一个正数等于加上一个负数, 即: 1-1 = 1 + (-1) = 0 , 所以机器可以只有加法而没有减法, 这样计算机运算的设计就更简单了.

于是人们开始探索 将符号位参与运算, 并且只保留加法的方法. 首先来看原码:

计算十进制的表达式: 1-1=0

1 - 1 = 1 + (-1) = [00000001] + [10000001] = [10000010] = -2

如果用原码表示, 让符号位也参与计算, 显然对于减法来说, 结果是不正确的.这也就是为何计算机内部不使用原码表示一个数.

为了解决原码做减法的问题, 出现了反码:

计算十进制的表达式: 1-1=0

1 - 1 = 1 + (-1) = [0000 0001] + [1000 0001]= [0000 0001] + [1111 1110] = [1111 1111] = [1000 0000] = -0

发现用反码计算减法, 结果的真值部分是正确的. 而唯一的问题其实就出现在"0"这个特殊的数值上. 虽然人们理解上+0和-0是一样的, 但是0带符号是没有任何意义的. 而且会有[0000 0000]和[1000 0000]两个编码表示0.

于是补码的出现, 解决了0的符号以及两个编码的问题:

1-1 = 1 + (-1) = [0000 0001] + [1000 0001] = [0000 0001] + [1111 1111] = [0000 0000]=[0000 0000]

这样0用[0000 0000]表示, 而以前出现问题的-0则不存在了.而且可以用[1000 0000]表示-128:

(-1) + (-127) = [1000 0001] + [1111 1111] = [1111 1111] + [1000 0001] = [1000 0000]

-1-127的结果应该是-128, 在用补码运算的结果中, [1000 0000] 就是-128. 但是注意因为实际上是使用以前的-0的补码来表示-128, 所以-128并没有原码和反码表示.(对-128的补码表示[1000 0000]补算出来的原码是[0000 0000], 这是不正确的)

使用补码, 不仅仅修复了0的符号以及存在两个编码的问题, 而且还能够多表示一个最低数.这就是为什么8位二进制, 使用原码或反码表示的范围为[-127, +127], 而使用补码表示的范围为[-128, 127].

因为机器使用补码, 所以对于编程中常用到的32位int类型, 可以表示范围是: [-231, 231-1] 因为第一位表示的是符号位.而使用补码表示时又可以多保存一个最小值.

 

四 原码, 反码, 补码 再深入

计算机巧妙地把符号位参与运算, 并且将减法变成了加法, 背后蕴含了怎样的数学原理呢?

将钟表想象成是一个1位的12进制数. 如果当前时间是6点, 我希望将时间设置成4点, 需要怎么做呢?我们可以:

1. 往回拨2个小时: 6 - 2 = 4

2. 往前拨10个小时: (6 + 10) mod 12 = 4

3. 往前拨10+12=22个小时: (6+22) mod 12 =4

2,3方法中的mod是指取模操作, 16 mod 12 =4 即用16除以12后的余数是4.

所以钟表往回拨(减法)的结果可以用往前拨(加法)替代!

现在的焦点就落在了如何用一个正数, 来替代一个负数. 上面的例子我们能感觉出来一些端倪, 发现一些规律. 但是数学是严谨的. 不能靠感觉.

首先介绍一个数学中相关的概念: 同余

 

同余的概念

两个整数a,b,若它们除以整数m所得的余数相等,则称a,b对于模m同余

记作 a ≡ b (mod m)

读作 a 与 b 关于模 m 同余。

举例说明:

4 mod 12 = 4

16 mod 12 = 4

28 mod 12 = 4

所以4, 16, 28关于模 12 同余.

 

负数取模

正数进行mod运算是很简单的. 但是负数呢?

下面是关于mod运算的数学定义:

clip_image001

上面是截图, "取下界"符号找不到如何输入(word中粘贴过来后乱码). 下面是使用"L"和"J"替换上图的"取下界"符号:

x mod y = x - y L x / y J

上面公式的意思是:

x mod y等于 x 减去 y 乘上 x与y的商的下界.

以 -3 mod 2 举例:

-3 mod 2

= -3 - 2xL -3/2 J

= -3 - 2xL-1.5J

= -3 - 2x(-2)

= -3 + 4 = 1

所以:

(-2) mod 12 = 12-2=10

(-4) mod 12 = 12-4 = 8

(-5) mod 12 = 12 - 5 = 7

 

开始证明

再回到时钟的问题上:

回拨2小时 = 前拨10小时

回拨4小时 = 前拨8小时

回拨5小时= 前拨7小时

注意, 这里发现的规律!

结合上面学到的同余的概念.实际上:

(-2) mod 12 = 10

10 mod 12 = 10

-2与10是同余的.

(-4) mod 12 = 8

8 mod 12 = 8

-4与8是同余的.

距离成功越来越近了. 要实现用正数替代负数, 只需要运用同余数的两个定理:

反身性:

a ≡ a (mod m)

这个定理是很显而易见的.

线性运算定理:

如果a ≡ b (mod m),c ≡ d (mod m) 那么:

(1)a ± c ≡ b ± d (mod m)

(2)a * c ≡ b * d (mod m)

如果想看这个定理的证明, 请看:http://baike.baidu.com/view/79282.htm

所以:

7 ≡ 7 (mod 12)

(-2) ≡ 10 (mod 12)

7 -2 ≡ 7 + 10 (mod 12)

现在我们为一个负数, 找到了它的正数同余数. 但是并不是7-2 = 7+10, 而是 7 -2 ≡ 7 + 10 (mod 12) , 即计算结果的余数相等.

接下来回到二进制的问题上, 看一下: 2-1=1的问题.

2-1=2+(-1) = [0000 0010] + [1000 0001]= [0000 0010] + [1111 1110]

先到这一步, -1的反码表示是1111 1110. 如果这里将[1111 1110]认为是原码, 则[1111 1110]原 = -126, 这里将符号位除去, 即认为是126.

发现有如下规律:

(-1) mod 127 = 126

126 mod 127 = 126

即:

(-1) ≡ 126 (mod 127)

2-1 ≡ 2+126 (mod 127)

2-1 与 2+126的余数结果是相同的! 而这个余数, 正式我们的期望的计算结果: 2-1=1

所以说一个数的反码, 实际上是这个数对于一个膜的同余数. 而这个膜并不是我们的二进制, 而是所能表示的最大值! 这就和钟表一样, 转了一圈后总能找到在可表示范围内的一个正确的数值!

而2+126很显然相当于钟表转过了一轮, 而因为符号位是参与计算的, 正好和溢出的最高位形成正确的运算结果.

既然反码可以将减法变成加法, 那么现在计算机使用的补码呢? 为什么在反码的基础上加1, 还能得到正确的结果?

2-1=2+(-1) = [0000 0010] + [1000 0001] = [0000 0010] + [1111 1111]

如果把[1111 1111]当成原码, 去除符号位, 则:

[0111 1111] = 127

其实, 在反码的基础上+1, 只是相当于增加了膜的值:

(-1) mod 128 = 127

127 mod 128 = 127

2-1 ≡ 2+127 (mod 128)

此时, 表盘相当于每128个刻度转一轮. 所以用补码表示的运算结果最小值和最大值应该是[-128, 128].

但是由于0的特殊情况, 没有办法表示128, 所以补码的取值范围是[-128, 127]

本人一直不善于数学, 所以如果文中有不对的地方请大家多多包含, 多多指点!


原文:http://www.cnblogs.com/zhangziqiu




结束了各种进制的转换,我们来谈谈另一个话题:原码、反码、补码。

我们已经知道计算机中,所有数据最终都是使用二进制数表达。

在计算机中,可以区分正负的类型,称为有符类型,无正负的类型(只有正值),称为无符类型。

数值类型分为整型或实型,其中整型又分为无符类型或有符类型,而实型则只有有符类型。

字符类型也分为有符和无符类型

关于原码反码补码,其实很简单:

① 正整数是不存在反码补码的,如果非要说,也得说正整数的原码反码补码都相等且等于该正整数的二进制表示;

② 负整数最高位为1(符号位),其补码是其反码加1,其反码是其原码除符号位外的位0→1,1→0;其原码则是该负整数绝对值对应的正整数的原码再在最高位上加个1(表示是负数)。

我们来看整数-1在计算机中如何表示。

假设这也是一个int类型,那么:

1、先取1的原码:00000000 00000000 00000000 00000001

2、得反码: 11111111 11111111 11111111 11111110

3、得补码: 11111111 11111111 11111111 11111111

可见,-1在计算机里用二进制表达就是全1。16进制为:0xFFFFFFFF。

计算机储存有符号的整数时,是用该整数的补码进行储存的,正数的原码、补码可以特殊理解为相同,负数的补码是它的反码加1出计算机数的补码表示法。数据的这种表示形式大大地简化了运算的处理过程。又因为减一个数可以代换以加这个数的相反数,使减法变成加法。那么什么是补码呢?我们先看一个例子,假定现在时钟上的读数是10点钟,问4小时之前是几点钟?即时钟上的读数是什么。答案是显而易见的,为:10 - 4 = 10 +(- 4)= 6(点)。但是,这完全可以换一种算法得到同样的结果:10 + 8 = 18(点)。显然,18(点)在时钟刻度盘上的读数是6(点)。常识告诉我们,时钟最大只能表示到12,超过12时就把12丢掉,再从0开始,即到达12 时又复位为0 。上式中的8是 12 - 4的结果;也即4是相对于12 的"补数"。因此,上式可表示为取模运算:10 - 4 = (10 + 8 )Mod (12) = 6 。

在计算机中,存储数据的单元就如刻度固定的时钟钟盘。对8位的单元而言,最大数(包括正负号)为 01111111,当到达010000000(=1111111 + 1)时就复位为00000000 。根据第2个特点,是丢失最高位上的"1"而得。

为了简化计算机的内部运算,数据在计算机内一律用补码表示之。这里,我们仍然以8位的单元(即字节)为例进行讨论。单元的最高1位表示数的正负号(称正负号位),其余7位表示数的绝对值(称数值位)。

(1)数的原码表示:原码是最简单的计算机数表示法。对正数,正负号位 = 0 ,数值位 = 数的绝对值。如,+0100101 的原码表示为:00100101。对负数,正负号位 = 1 ,数值位 = 数的绝对值。如,- 0100101 表示为:10100101(=10000000 - (- 0100101) = 100000000 + 0100101 = 10100101)。因此,有原码的生成公式为:

(2)数的反码表示:对正数:同原码表示 。如,+0100101 表示为00100101。对负数,先将其表示为绝对值(正数)的原码,然后将每一位的数变反,即0变为1,1变为0 ,得负数的反码 。如,- 0100101 的反码是:先表示为00100101 ,再将每一位二进位变反为11011010。这个结果恰相当于计算11111111 + (- 00100101) = 11111111 - 00100101 = 11011010。其中,11111111 = 2 8 - 1 。因此,有反码的生成公式为:

(3)数的补码表示:对正数,同原码表示 。如,+0100101 表示为00100101。对负数,先将其表示为反码,然后在该反码的最低位加"1",即得到它的补码 。如,- 0100101 先将其表示为反码为11011010 ,再在最低位加"1"得补码为11011011。这个结果恰相当于计算100000000 - 00100101 = 11011011。因此,有补码的生成公式为:

由上可知:对于正数,原码、反码和补码是一致的。而对负数则三码不同。反码为生成补码提供工具。可见,补码的提出主要是针对负数的。对一个负数求其补码,我们就说对这个数取补。其取补过程就是:先将其绝对值表示为原码,然后堆砌取反(求出反码),最好再加"1",即得数的补码。现在,读者必须建立起这样一种观念:数据在机内的实际表示或存储都是补码形式;对补码不再考虑正负号,尽管还能从正负号位为0还是为1认定一个数的正负。

“模”是指一个计量系统的计数范围。如时钟等。计算机也可以看成一个计量机器,它也有一个计量范围,即都存在一个“模”。例如:

时钟的计量范围是0~11,模=12。

表示n位的计算机计量范围是0~2(n)-1,模=2(n)。【注:n表示指数】

“模”实质上是计量器产生“溢出”的量,它的值在计量器上表示不出来,计量器上只能表示出模的余数。任何有模的计量器,均可化减法为加法运算。

例如: 假设当前时针指向10点,而准确时间是6点,调整时间可有以下两种拨法:

一种是倒拨4小时,即:10-4=6

另一种是顺拨8小时:10+8=12+6=6

在以12模的系统中,加8和减4效果是一样的,因此凡是减4运算,都可以用加8来代替。

对“模”而言,8和4互为补数。实际上以12模的系统中,11和1,10和2,9和3,7和5,6和6都有这个特性。共同的特点是两者相加等于模。

对于计算机,其概念和方法完全一样。n位计算机,设n=8,所能表示的最大数是11111111,若再加1称为100000000(9位),但因只有8位,最高位1自然丢失。又回了00000000,所以8位二进制系统的模为2(8)。 在这样的系统中减法问题也可以化成加法问题,只需把减数用相应的补数表示就可以了。

把补数用到计算机对数的处理上,就是补码

无符号的整数根本就没有原码、反码和补码,其他的类型一概没有。虽然我们也可以用二进制中最小的数去对应最小的负数,最大的也相对应,但是那样不科学,下面来说说科学的方法。还是说一个字节的整数,不过这次是有符号的啦,1个字节它不管怎么样还是只能表示256个数,因为有符号所以我们就把它表示成范围:-128-127。它在计算机中是怎么储存的呢?可以这样理解,用最高位表示符号位,如果是0表示正数,如果是1表示负数,剩下的7位用来储存数的绝对值的话,能表示27个数的绝对值,再考虑正负两种情况,27*2 还是256个数。首先定义0在计算机中储存为00000000,对于正数我们依然可以像无符号数那样换算,从00000001到01111111依次表示 1到127。那么这些数对应的二进制码就是这些数的原码。到这里很多人就会想,那负数是不是从10000001到11111111依次表示-1到- 127,那你发现没有,如果这样的话那么一共就只有255个数了,因为10000000的情况没有考虑在内。实际上,10000000在计算机中表示最小的负整数,就是这里的-128,而且实际上并不是从10000001到11111111依次表示-1到-127,而是刚好相反的,从10000001到 11111111依次表示-127到-1。负整数在计算机中是以补码形式储存的,总结一下,计算机储存有符号的整数时,是用该整数的补码进行储存的,0的原码、补码都是0,正数的原码、补码可以特殊理解为相同,负数的补码是它的反码加1。下面再多举几个例子,来帮助大家理解!

十进制 → 二进制  (怎么算?要是不知道看计算机基础的书去)

47   → 101111

有符号的整数    原码    反码    补码

47      00101111  00101111  00101111(正数补码和原码、反码相同,不能从字面理解)

-47      10101111  11010000  11010001(负数补码是在反码上加1)

再举个例子,学C语言的同学应该做过这道题:

把-1以无符号的类型输出,得什么结果?(程序如下)

#include <stdio.h>

int main(void)

{

short int n=-1;

printf("%u",(unsigned short int)n);

}

首先在我的电脑中short int类型的储存空间是2个字节,你的可能不同,我说过,这取决于你的计算机配置。它能储存28*2=65536个不同的数据信息,如果是无符号那么它的范围是0~65535(0~216-1),如果是有符号,那么它的范围是-32768~32767(-215~215-1)。这道题目中,开始n是一个有符号的短整型变量,我们给它赋值为-1,根据我们前面所说的,它在计算机中是以补码11111111 11111111储存的,注意前面说了是2个字节。如果把它强制为无符号的短整型输出的话,那么我们就把刚才的二进制把看成无符号的整型在计算机中储存的形式,对待无符号的整型就没有什么原码、反码和补码的概念了,直接把11111111 11111111转化成十进制就是65535,其实我们一看都是一就知道它是范围中最大的一个数了。呵呵,就这么简单。你个把上面的源代码编译运行看看,如果你的电脑short int也是两个字节,那就会和我得一样的结果。


原文链接:http://www.rxyj.org/html/2010/0803/2973162.php




问题:

在正数情况下,原码、反码、补码都是它本身,但是这与补码加原码恰好等于2n次方矛盾?


解答:

原码、反码、补码最初是针对负数设计的,其目的是为了在数字电路中用加法实现减法运算,故需要将负数先转换成其补码形式,先利用数字电路中加法器进行运算,再将运算结果转换成对应的数(正数不变,负数再求补),这样就可以用数字电路中加法器实现减法运算。我们所说的补码加原码恰好等于2n次方是针对负数而言,对正数,计算时不需要进行反码、补码转换,所以我们规定其原码、反码、补码都是它本身,所以补码加原码恰好等于2n次方对正数就不适用了。




C语言 数据类型(原码反码补码)


结束了各种进制的转换,我们来谈谈另一个话题:原码、反码、补码。

我们已经知道计算机中,所有数据最终都是使用二进制数表达。

在计算机中,可以区分正负的类型,称为有符类型,无正负的类型(只有正值),称为无符类型。

数值类型分为整型或实型,其中整型又分为无符类型或有符类型,而实型则只有有符类型。

字符类型也分为有符和无符类型

关于原码反码补码,其实很简单:

① 正整数是不存在反码补码的,如果非要说,也得说正整数的原码反码补码都相等且等于该正整数的二进制表示;

② 负整数最高位为1(符号位),其补码是其反码加1,其反码是其原码除符号位外的位0→1,1→0;其原码则是该负整数绝对值对应的正整数的原码再在最高位上加个1(表示是负数)。

我们来看整数-1在计算机中如何表示。

假设这也是一个int类型,那么:

1、先取1的原码:00000000 00000000 00000000 00000001

2、得反码: 11111111 11111111 11111111 11111110

3、得补码: 11111111 11111111 11111111 11111111

可见,-1在计算机里用二进制表达就是全1。16进制为:0xFFFFFFFF。

计算机储存有符号的整数时,是用该整数的补码进行储存的,正数的原码、补码可以特殊理解为相同,负数的补码是它的反码加1出计算机数的补码表示法。数据的这种表示形式大大地简化了运算的处理过程。又因为减一个数可以代换以加这个数的相反数,使减法变成加法。那么什么是补码呢?我们先看一个例子,假定现在时钟上的读数是10点钟,问4小时之前是几点钟?即时钟上的读数是什么。答案是显而易见的,为:10 - 4 = 10 +(- 4)= 6(点)。但是,这完全可以换一种算法得到同样的结果:10 + 8 = 18(点)。显然,18(点)在时钟刻度盘上的读数是6(点)。常识告诉我们,时钟最大只能表示到12,超过12时就把12丢掉,再从0开始,即到达12 时又复位为0 。上式中的8是 12 - 4的结果;也即4是相对于12 的"补数"。因此,上式可表示为取模运算:10 - 4 = (10 + 8 )Mod (12) = 6 。

在计算机中,存储数据的单元就如刻度固定的时钟钟盘。对8位的单元而言,最大数(包括正负号)为 01111111,当到达010000000(=1111111 + 1)时就复位为00000000 。根据第2个特点,是丢失最高位上的"1"而得。

为了简化计算机的内部运算,数据在计算机内一律用补码表示之。这里,我们仍然以8位的单元(即字节)为例进行讨论。单元的最高1位表示数的正负号(称正负号位),其余7位表示数的绝对值(称数值位)。

(1)数的原码表示:原码是最简单的计算机数表示法。对正数,正负号位 = 0 ,数值位 = 数的绝对值。如,+0100101 的原码表示为:00100101。对负数,正负号位 = 1 ,数值位 = 数的绝对值。如,- 0100101 表示为:10100101(=10000000 - (- 0100101) = 100000000 + 0100101 = 10100101)。因此,有原码的生成公式为:

(2)数的反码表示:对正数:同原码表示 。如,+0100101 表示为00100101。对负数,先将其表示为绝对值(正数)的原码,然后将每一位的数变反,即0变为1,1变为0 ,得负数的反码 。如,- 0100101 的反码是:先表示为00100101 ,再将每一位二进位变反为11011010。这个结果恰相当于计算11111111 + (- 00100101) = 11111111 - 00100101 = 11011010。其中,11111111 = 2 8 - 1 。因此,有反码的生成公式为:

(3)数的补码表示:对正数,同原码表示 。如,+0100101 表示为00100101。对负数,先将其表示为反码,然后在该反码的最低位加"1",即得到它的补码 。如,- 0100101 先将其表示为反码为11011010 ,再在最低位加"1"得补码为11011011。这个结果恰相当于计算100000000 - 00100101 = 11011011。因此,有补码的生成公式为:

由上可知:对于正数,原码、反码和补码是一致的。而对负数则三码不同。反码为生成补码提供工具。可见,补码的提出主要是针对负数的。对一个负数求其补码,我们就说对这个数取补。其取补过程就是:先将其绝对值表示为原码,然后堆砌取反(求出反码),最好再加"1",即得数的补码。现在,读者必须建立起这样一种观念:数据在机内的实际表示或存储都是补码形式;对补码不再考虑正负号,尽管还能从正负号位为0还是为1认定一个数的正负。

“模”是指一个计量系统的计数范围。如时钟等。计算机也可以看成一个计量机器,它也有一个计量范围,即都存在一个“模”。例如:

时钟的计量范围是0~11,模=12。

表示n位的计算机计量范围是0~2(n)-1,模=2(n)。【注:n表示指数】

“模”实质上是计量器产生“溢出”的量,它的值在计量器上表示不出来,计量器上只能表示出模的余数。任何有模的计量器,均可化减法为加法运算。

例如: 假设当前时针指向10点,而准确时间是6点,调整时间可有以下两种拨法:

一种是倒拨4小时,即:10-4=6

另一种是顺拨8小时:10+8=12+6=6

在以12模的系统中,加8和减4效果是一样的,因此凡是减4运算,都可以用加8来代替。

对“模”而言,8和4互为补数。实际上以12模的系统中,11和1,10和2,9和3,7和5,6和6都有这个特性。共同的特点是两者相加等于模。

对于计算机,其概念和方法完全一样。n位计算机,设n=8,所能表示的最大数是11111111,若再加1称为100000000(9位),但因只有8位,最高位1自然丢失。又回了00000000,所以8位二进制系统的模为2(8)。 在这样的系统中减法问题也可以化成加法问题,只需把减数用相应的补数表示就可以了。

把补数用到计算机对数的处理上,就是补码

无符号的整数根本就没有原码、反码和补码,其他的类型一概没有。虽然我们也可以用二进制中最小的数去对应最小的负数,最大的也相对应,但是那样不科学,下面来说说科学的方法。还是说一个字节的整数,不过这次是有符号的啦,1个字节它不管怎么样还是只能表示256个数,因为有符号所以我们就把它表示成范围:-128-127。它在计算机中是怎么储存的呢?可以这样理解,用最高位表示符号位,如果是0表示正数,如果是1表示负数,剩下的7位用来储存数的绝对值的话,能表示27个数的绝对值,再考虑正负两种情况,27*2 还是256个数。首先定义0在计算机中储存为00000000,对于正数我们依然可以像无符号数那样换算,从00000001到01111111依次表示 1到127。那么这些数对应的二进制码就是这些数的原码。到这里很多人就会想,那负数是不是从10000001到11111111依次表示-1到- 127,那你发现没有,如果这样的话那么一共就只有255个数了,因为10000000的情况没有考虑在内。实际上,10000000在计算机中表示最小的负整数,就是这里的-128,而且实际上并不是从10000001到11111111依次表示-1到-127,而是刚好相反的,从10000001到 11111111依次表示-127到-1。负整数在计算机中是以补码形式储存的,总结一下,计算机储存有符号的整数时,是用该整数的补码进行储存的,0的原码、补码都是0,正数的原码、补码可以特殊理解为相同,负数的补码是它的反码加1。下面再多举几个例子,来帮助大家理解!

十进制 → 二进制  (怎么算?要是不知道看计算机基础的书去)

47   → 101111

有符号的整数    原码    反码    补码

47      00101111  00101111  00101111(正数补码和原码、反码相同,不能从字面理解)

-47      10101111  11010000  11010001(负数补码是在反码上加1)

再举个例子,学C语言的同学应该做过这道题:

把-1以无符号的类型输出,得什么结果?(程序如下)

#include <stdio.h>

int main(void)

{

short int n=-1;

printf("%u",(unsigned short int)n);

}

首先在我的电脑中short int类型的储存空间是2个字节,你的可能不同,我说过,这取决于你的计算机配置。它能储存28*2=65536个不同的数据信息,如果是无符号那么它的范围是0~65535(0~216-1),如果是有符号,那么它的范围是-32768~32767(-215~215-1)。这道题目中,开始n是一个有符号的短整型变量,我们给它赋值为-1,根据我们前面所说的,它在计算机中是以补码11111111 11111111储存的,注意前面说了是2个字节。如果把它强制为无符号的短整型输出的话,那么我们就把刚才的二进制把看成无符号的整型在计算机中储存的形式,对待无符号的整型就没有什么原码、反码和补码的概念了,直接把11111111 11111111转化成十进制就是65535,其实我们一看都是一就知道它是范围中最大的一个数了。呵呵,就这么简单。你个把上面的源代码编译运行看看,如果你的电脑short int也是两个字节,那就会和我得一样的结果。


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
原码反码补码计算口诀是: 1. 原码:符号位加上真值的绝对值。 2. 反码:将原码中的符号位保持不变,其余位取反。 3. 补码反码加1。 例如,对于一个8位二进制数,如果要计算其反码,可以按照以下步骤进行: 1. 将符号位保持不变。 2. 将其余位取反。 对于补码的计算,可以按照以下步骤进行: 1. 先计算其反码。 2. 在反码的基础上加1。 这样,就可以得到原码、反码补码的计算结果。 #### 引用[.reference_title] - *1* [原码, 反码, 补码的基础概念和计算方法](https://blog.csdn.net/Chinajsczlymyc/article/details/126910306)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [(转)java 原码反码补码计算 以及 取反运算,原码反码补码运算公式](https://blog.csdn.net/PacosonSWJTU/article/details/128604733)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [原码,补码,反码概念和计算方法详解](https://blog.csdn.net/qq_39541098/article/details/122729622)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值