数据的表示:原码、反码、补码、移码以及浮点数的运算
前言
复习到数据表示方面相关的知识,所以在这里做一下记录,也方便大家参考。
什么是 R 进制
对于 R
机制,如果要实现与十进制的转换,则使用 按权展开法,其具体操作为:
将
R
进制数的每一位数值用 RkR^kRk 的形式表示,即幂底数为R
,指数为k
,k
与该位和小数点间的间距有关。当该位位于小数点左边时,k
则是该位和小数点之间数码的个数;而当该位维语小数点右边时,则k
是负值,其绝对值为该位和小数点之间数码的个数加1
。
比如二进制和十进制之间的转换: 10111.01=1∗24+1∗22+1∗21+1∗20+1∗2−210111.01 = 1* 2^4+1*2^2+1*2^1+1*2^0+1*2^{-2}10111.01=1∗24+1∗22+1∗21+1∗20+1∗2−2。
再比如七进制和十进制之间的转换:403.02=4∗72+3∗70+2∗7−2403.02 =4*7^2+3*7^0+2*7^{-2}403.02=4∗72+3∗70+2∗7−2
进制之间的转换
- 十进制转
R
进制
使用 短除法,比如我们要将 100100100 转换为二进制数,则有如下过程,最终的结果为 1100100B1100100B1100100B。
- 二进制转八/十六进制
假设我们有一个二进制数 100010010011100010010011100010010011,如果我们要将其转换为八进制数,一个八进制数需要 8 个基数来表示,所以需要 3 位二进制来表示。那么转换过程如下,即对应的八进制数为 4223O4223O4223O。
而如果我们将要将其转换为十六进制数,一个十六进制数需要 16 个基数来表示,所以需要 4 位二进制来表示。则对应的转换过程如下,即对应的十六进制数为 893H893H893H。
码制
计算机中,无论我们要存储任何数据,它都会转换为二进制码进行存储。现在的计算机中,如果我们要进行加法运算操作,那么我们很容易实现,因为现在的计算机体系大多采用冯诺依曼所提出的经典计算机体系结构,其中就包含了加法运算器。但如果我们要进行减法运算,那么此时就犯难了。没有减法运算器,我们要如何实现减法运算呢?而针对这一问题,原码、反码、补码就产生了。我们常用这三种码来表示一个机器数,从而解决计算机做减法的问题。下面是几个数的实例(000 的补码只有一种表现形式),下面就分别来看看几种不同表示法的具体知识。
1 | -1 | +0 | -0 | |
---|---|---|---|---|
原码 | 000000010000 000100000001 | 100000011000000110000001 | 000000000000000000000000 | 100000001000000010000000 |
反码 | 000000010000000100000001 | 111111101111111011111110 | 000000000000000000000000 | 111111111111111111111111 |
补码 | 000000010000000100000001 | 111111111111111111111111 | 000000000000000000000000 | 000000000000000000000000 |
- 符号位
正式了解不同码制之前,我们先来看看符号位的定义。所谓符号位,是在内存中存放的最左边的一位,如果该位为 000,那么说明这个数表示的是正数;而假如该位为 111,那么就说明这个数表示的是负数。
- 原码
是一种最简单的机器数表示法,我们常用最高位来表示符号位,0
为正,1
为负,而用余下的其他位来存放该数二进制的绝对值。也即除开符号位之外,原码的数据位就是一个数的二进制绝对值表示。
在上面的示例中,我们发现,虽然 000 和 −0-0−0 的原码不一致,但是主要还是符号位的不同,我们再用上面的示例来进行运算:
0001+0010=0011,1+2=30001 + 0010=0011,1 + 2 = 30001+0010=0011,1+2=3
0000+1000=1000,0+(−0)=−00000 + 1000= 1000,0 + (-0)=-00000+1000=1000,0+(−0)=−0
0001+1001=1010,1+(−1)=−20001+1001=1010,1+(-1)=-20001+1001=1010,1+(−1)=−2
可以发现,如果我们只是进行正数之间的加法运算,是不会出现问题的。但一旦出现正负数相加的情况,就会导致错误结果,实际运算的结果与预期相反。这主要是因为符号位所引起。那有没有相应的解决办法呢?别着急,我们接下来去看看反码。
- 反码
虽然原码很简单,但是存在的最大问题在于如果一个数加上其相反数结果不为 000,即 1+(−1)1 + (-1)1+(−1) 的结果不为 000,为了解决这个问题,才有了反码的出现。而针对反码,这里也分为两种情况:
- 如果一个数是正数,那么其反码和原码一样,如 111 的原码和反码均为 000100010001。
- 如果一个数是负数,那么其反码就是其原码除符号位之外,按位取反。如 −1-1−1 的原码为 100110011001,其反码为 111011101110。
这个时候我们再来看看原码中存在的问题:
0001+1001=1111,1+(−1)=−00001+1001=1111,1+(-1)=-00001+1001=1111,1+(−1)=−0
可以看到通过使用反码,我们解决了源码中两个相反数之和不为 000 的情况,但是不是就代表我们可以用反码来进行通用减法运算呢?我们来试试两个不同的负数相加:
1110+1100=1010,(−1)+(−3)=−51110+1100=1010,(-1)+(-3)=-51110+1100=1010,(−1)+(−3)=−5
就离谱,这结果明显错误!所以反码还是不能彻底解决减法运算的问题。而相应的,科学家们又提出了补码这一概念。
- 补码
同样的,补码也很特殊,针对正负数也分为了两种情况:
- 如果一个数是正数,那么该数的补码等于其原码,如 111 的原码和补码均为 000100010001。
- 如果一个数是负数,那么该数的补码等于反码 +1+1+1,如 −1-1−1 的反码为
1110
,那么其补码即为1111
。
同样,我们来试试看反码中进行减法运算所出现错误的情况:
1111+1111=1110,(−1)+(−1)=−21111+1111=1110,(-1)+(-1)=-21111+1111=1110,(−1)+(−1)=−2
诶,完美解决了反码中两个负数相加时所出现的结果错误的情况。因此在计算机中,为了避免运算错误,都是采用的补码进行加减法运算。
- 不同码制之间的转换总结
经过上面的各种码制介绍之后,我们将一个数的不同码制之间的转换规律总结如下图:
- 移码
除开常用的原码、反码、补码之外,还有一种码制叫做移码。所谓移码,又叫做增码或者偏置码,它是在数 XXX 上增加一个偏移量来定义的,通常用来表示浮点数的阶码,其表示形式类似于补码,只是其符号位用 111 来表示正数,000 来表示负数,则数值表示部分则是与补码相同。
1 | -1 | +0 | -0 | |
---|---|---|---|---|
原码 | 000000010000 000100000001 | 100000011000000110000001 | 000000000000000000000000 | 100000001000000010000000 |
反码 | 000000010000000100000001 | 111111101111111011111110 | 000000000000000000000000 | 111111111111111111111111 |
补码 | 000000010000000100000001 | 111111111111111111111111 | 000000000000000000000000 | 000000000000000000000000 |
移码 | 100000011000000110000001 | 011111110111111101111111 | 100000001000000010000000 | 000000000000000000000000 |
数值表示范围
在开始了解数值的表示范围之前,我们先来了解下什么叫做定点。所谓定点,是因为小数点的位置是固定的,所以我们叫做数值是定点的整数或者小数。假如一个数值用码制的形式表示, 如果小数点在数值最低位(也即最后边)是,此时该数表示的是定点整数。但如果小数点在介于数值最高位和最低位的中间位置,那么此时该数所表示的就是一个定点小数。
码制 | 定点整数 | 定点小数 |
---|---|---|
原码 | −(2n−1−1)-(2^{n-1}-1)−(2n−1−1)~+(2n−1−1)+(2^{n-1}-1)+(2n−1−1) | −(1−2−(n−1))-(1-2^{-(n-1)})−(1−2−(n−1))~+(1−2−(n−1))+(1-2^{-(n-1)})+(1−2−(n−1)) |
反码 | −(2n−1−1)-(2^{n-1}-1)−(2n−1−1)~+(2n−1−1)+(2^{n-1}-1)+(2n−1−1) | −(1−2−(n−1))-(1-2^{-(n-1)})−(1−2−(n−1))~+(1−2−(n−1))+(1-2^{-(n-1)})+(1−2−(n−1)) |
补码 | −2n−1-2^{n-1}−2n−1~+(2n−1−1)+(2^{n-1}-1)+(2n−1−1) | −1-1−1~+(1−2−(n−1))+(1-2^{-(n-1)})+(1−2−(n−1)) |
移码 | −2n−1-2^{n-1}−2n−1~+(2n−1−1)+(2^{n-1}-1)+(2n−1−1) | −1-1−1~+(1−2−(n−1))+(1-2^{-(n-1)})+(1−2−(n−1)) |
假设我们用 8 个数位来表示一个数值,那么对于定点整数而言,其原码范围就是:
−(2n−1−1)-(2^{n-1}-1)−(2n−1−1) ~ +(2n−1−1),−127+127+(2^{n-1}-1),-127~+127+(2n−1−1),−127 +127
将其转换为二进制就是:−11111111-11111111−11111111 ~ 011111110111111101111111,那么我们就可以得到该数值补码的范围:100000001000000010000000 ~ 011111110111111101111111。
同样的,对于定点小数而言,我们用 8 个数位来表示,则其原码范围是:
−(1−2−(n−1))-(1-2^{-(n-1)})−(1−2−(n−1)) ~ +(1−2−(n−1))+(1-2^{-(n-1)})+(1−2−(n−1))
同样将其转换为二进制:−0.1111111-0.1111111−0.1111111 ~ +0.1111111+0.1111111+0.1111111,此时我们就可以得到其对应的补码范围:−1-1−1 ~ +0.1111111+0.1111111+0.1111111。
浮点数的运算
浮点数的表示
所谓浮点数,指的是小数点位置不固定的数,相比整数能够表示更大的范围,其表示格式如下:
对于一个浮点数 NNN,我们常用如下形式表示:
N=M∗ReN = M * R^eN=M∗Re
其中 MMM 叫做 尾数,RRR 叫做 基数,而 eee 则叫做 指数。其中,指数也叫做阶码,它的位数决定了数值的表示范围,位数越多说明表示的范围越大;而尾数的位数则决定了数值的有效精度,位数越多说明该数的精度越高。
例如对于一个整数 100010001000,用浮点数的形式表示即为 1000=1.0∗1031000 = 1.0 * 10^31000=1.0∗103,其中 1.01.01.0 就对应着浮点数表示形式中的尾数,而 101010 则对应着基数,333 则对应着指数。
浮点数运算
既然整数也可以用浮点数的形式表示,那我们就可以把所有的运算都看做是浮点数运算。要进行浮点数运算,我们又该如何进行呢?
我们以一个实例来看看,浮点数之间应该如何进行运算。
假设有如下两个数:m=1.0∗103m = 1.0*10^3m=1.0∗103 和 n=2.5∗102n = 2.5*10^2n=2.5∗102,要对两个数进行加法运算。
首先,我们发现两个数的指数是不一样的,那要进行加法运算,我们首先将其统一为一个指数,比如统一指数为 222 或者 333。按理来讲,任何一个指数都是可以的,但如果我们转换为小的指数(222),那么 m=10.0∗102m = 10.0*10^2m=10.0∗102,让其与 nnn 进行加法运算得到的结果到时候又需要转换为大的指数(2−>32 -> 32−>3),此时就显得比较麻烦。所以为了避免结果运算之后再次进行指数的转换,我们 一般推荐统一为大的指数(333)。所以我们统一指数之后,得到的两个数分别是:
m=1.0∗103m = 1.0*10^3m=1.0∗103
n=0.25∗103n=0.25*10^3n=0.25∗103
指数统一之后,我们再来计算尾数,此时尾数则为 1.0+0.25=1.251.0+0.25=1.251.0+0.25=1.25。
最后,我们既然得到了尾数、指数和基数,那么对结果进行格式化操作,得到 m+n=1.25∗103m + n=1.25*10^3m+n=1.25∗103。注意这里比较特殊,因为我们的结果是很规范的浮点数(即尾数小数点的左边既不能为 000,也不能是 111 位以上的数),假设我们的浮点数不是规范的浮点数,那么则需要对其进行格式化操作。
总结起来浮点数的运算过程就是:
对阶 -> 尾数计算 -> 格式化结果
总结
好了,以上就是今天的所有内容了。
主要讲了关于 R
进制的表示,以及如何与十进制进行转换。然后对常见的进制之间的转换做了介绍,接着则是对原码、反码、补码、移码等不同码制之间的转换。最后则是对数值表示范围进行了介绍,以及浮点数运算的相关知识进行补充。
创作不易,如果你觉得我的文章内容对你有所帮助,那就点个赞再走吧!
数据的表示:原码、反码、补码、移码以及浮点数的运算相关推荐
- 计算机中的原码,计算机中的原码反码补码移码
计算机中的原码反码补码移码 原码 数值 X 的原码记为 [X]原,如果机器字长为 n (即采用 n 个二进制位表示数据),则最高位是符号位,0 表示正号,1 表示负号,基余的 n~1 位表示数值的绝对 ...
- 计算机组成原理——基本组成 进制转化 奇偶校验 原码 反码 补码 移码 移位 原码补码乘法除法 IEEE754 加法器ALU
笔记来源于王道考研视频 第一章 通过电信号传递信息(低电平代表0,高电平代表1) 计算机系统 计算机系统=硬件+软件 软件 系统软件 应用软件 操作系统,数据库管理系统(DBMS),标准程序库(编程时 ...
- 【计算机组成原理】原码 反码 补码 移码的转换
原码 反码 补码 移码的转换 这三种机器码都是二进制数据的表现形式,可以表现正数和负数. 原码是可以直接表现出数据的正负和大小. 正数的原码.反码和补码都是相同的. 反码用于原码和补码的转换的功能. ...
- 【软考学习2】数据表示——原码 反码 补码 移码
原码 反码 补码 移码是软考必考的项目,所以需要对其概念.计算方式和取值范围进行总结. 零.使用场景 原码 反码 补码 移码都是计算机中表示数据的方式,各有所长,对于我们来说,都需要加以学习. 软考中 ...
- 原码, 反码, 补码, 移码 详解
本篇文章讲解了计算机的原码, 反码和补码. 并且进行了深入探求了为何要使用反码和补码, 以及更进一步的论证了为何可以用反码, 补码的加法计算原码的减法. 论证部分如有不对的地方请各位牛人帮忙指正! 希 ...
- [例题详解]真值 机器数概念 | 原码 反码 补码 移码 概念及加减计算
目录 真值和机器数 原码 反码 补码 移码 对比记忆 | 原 反 补 移码 加减法 | 原码 补码 结语 | 大学生学习复习资料 真值和机器数 真值:-5.+10 机器数(带符号数)(= 符号位 [0 ...
- 原码 反码 补码 移码
原码 反码 补码 移码 在计算机内,机器数分为无符号数和有符号数 无符号数表示正数 没有符号位 原码:最高位为符号位 正数为0 负数为1 反码:原码符号位不变 其余位取反 补码:反码+1 移码:反码的 ...
- 原码 反码 补码 移码(变补)补码与移码的作用
定义 正数: 原码=反码=补码 负数: 原码:符号位+数值位 (符号位0为正数,1为负数) eq: -7 :10000111 反码:符号位不变,其它位取反:11111000 补码:反码+1:11111 ...
- 2.2.1 定点数的表示 原码 反码 补码 移码
没有未来的未来不是我想要的未来 o(╥﹏╥)o (つД`)(ノへ ̄.)哭了 学习的是定点数的表示,那我们首先来认识一下什么叫定点数与定点数相对应的另一个概念叫做浮点数所谓定点数就是指小数点的位置固定不 ...
- 【计算机组成原理】原码 反码 补码 移码
目录 一.原码.反码.补码.移码的概念 1. 真值 2. 机器数 1. 原码 2. 反码 3. 补码 4. 移码 二.原码.反码.补码.移码的转换 1. 原码转反码 2. 原码转补码 3. 原码转移码 ...
最新文章
- 干货:Android 源码使用心得分享
- Vue 之qs 使用详解
- mysql安装尝试创建新用户失败_Linux MySQL yum安装 创建新用户
- Redis中的I/O 多路复用(I/O Multiplexing)
- .NET Core采用的全新配置系统[7]: 将配置保存在数据库中
- 私有方法与静态私有方法_每个私有静态方法都是新类的候选人
- Error running tomcat8 Address localhost:1099 is already in use 错误解决
- c++ 访问控制与封装
- Vue 3.0暂缓发布,前端同学暂时舒了一口气
- Jboss启动报错——DailyRollingFileAppender无法转换异常
- shell判断进程使用CPU时间后kill进程
- MongoDB介绍与部署使用
- java applet介绍,Java Applet教程介绍
- 精选16款超精美的XP登录界面下载
- LVGL (7) 显示对接
- appserver安装教程
- 数据库中间件选型思考和实战
- 给asus eeepc 1015pw的 1301版本的 bios添加slic2.1
- 广义拉格朗日函数的理解
- 蓝牙助手android,蓝牙助手手机版