进制的定义:进制是一种计数方式,也称为进位计数法或者位值计数法,使用有限数字符号表示无限的数值,使用的数字符号的数目称为这种进位制的基数或者底数,例如十进制就是由0-9十个数字组成。html
在计算机内存中,都是以二进制的补码形式来存储数据的,生活中以十进制方式计算的数据居多,例如帐户余额,开发人员的薪水等等。计算的内存地址、MAC地址等等一般都是使用十六进制表示的,Linux系统的权限系统采用八进制的数据表示的。编程
相同进制类型数据进行运算时会遵照加法:逢R进1;减法:借1当R,其中R就表示进制。数组
以下表格是计算机经常使用进制的组成、示例和使用场景:架构
进制名称 | 组成 | 数值示例 | 典型使用场景 |
---|---|---|---|
二进制 | 0,1 | 101 | 内存数据存储 |
八进制 | 0-7之间的8个整数 | 012(以0开头) | Linux权限 |
十进制 | 0-9之间的10个整数 | 12 | 整数 |
十六进制 | 0-9,a-f之间的10个数字加6个字母 | 12f | 数据的内存地址 |
咱们目前主要使用的计算机都是大规模集成电路机,是采用大规模和超大规模的集成电路做为逻辑元件的。学习
集成电路,按其功能、结构的不一样,能够分为模拟集成电路、数字集成电路和数/模混合集成电路三大类。而咱们的计算机主要是采用数字集成电路搭建的。spa
逻辑门是数字逻辑电路的基本单元。常见的逻辑门包括“与”门,“或”门,“非”门,“异或”等等。经过逻辑门能够组合使用实现更为复杂的逻辑运算和数值运算。code
逻辑门能够经过控制高、低电平,从而实现逻辑运算。电源电压大小的波动对其没有影响,温度和工艺误差对其工做的可靠性影响也比模拟电路小得多,因此相对稳定。orm
由于数字计算机是由逻辑门组成,而逻辑电路最基础的状态就是两个——开和关。因此,数字电路是以二进制逻辑代数为数学基础。二进制的基本运算规则简单,运算操做方便,这样一来有利于简化计算机内部结构,提升运算速度。htm
可是在平常开发中,一般都会使用八进制和十六进制,由于八进制和十六进制相对于二进制表示数据更加简洁,并且一个八进制表示三个二进制,一个十六进制表示四个二进制。blog
例如 1024使用二进制表示为0b100 0000 0000,使用八进制表示为0o2000,使用十六进制表示为0x400。
首先明确不一样进制的值是如何计算的,这里以十进制和二进制为例子,阐述它们的计算过程。
十进制1024
1024=1*10^3+2*10^1+4*10^0=1000+20+4=1024
二进制的0b10000000000
0b10000000000 =1*2^10=1024
二进制整数转十进制整数是使用按权展开法计算的,这里以二进制数据01100101为例子。
从右往左开始数,若是二进制位为1,则依次用1*2^n,n从0开始。
01100101 转换为十进制的计算过程以下所示
01100101=1*2^6+1*2^5+1*2^2+1*2^0=64+32+4+1=101
十进制整数转二进制整数是采用重复相除法来实现的,具体的实现就是将十进制的整数除以2,求余数,直到商数为0,而后将余数倒转的结果就是十进制转二进制的结果。
以十进制101为例子,转换为二进制的计算过程以下表格所示
重复除以2 | 商数 | 余数 |
---|---|---|
101/2 | 50 | 1 |
50/2 | 25 | 0 |
25/2 | 12 | 1 |
12/2 | 6 | 0 |
6/2 | 3 | 0 |
3/2 | 1 | 1 |
1/2 | 0 | 1 |
而后将余数的结果从下到上串联起来的结果:1100101,即十进制的101转换为二进制的结果为1100101
再来一个例子:将十进制的237转换为二进制
重复除以2 | 商数 | 余数 |
---|---|---|
237/2 | 118 | 1 |
118/2 | 59 | 0 |
59/2 | 29 | 1 |
29/2 | 14 | 1 |
14/2 | 7 | 0 |
7/2 | 3 | 1 |
3/2 | 1 | 1 |
1/2 | 0 | 1 |
而后将余数的结果从下到上串联起来的结果:11101101,即十进制的237转换为二进制的结果为11101101。
二进制的小数转换为十进制的小数也是使用按权展开法计算的,只不过首先是从左向右数,从2-1依次递减开始计算的,2-1就是除以2,2^-2就是除以4,依次类推。
例如小数0.11001转换为十进制的计算过程以下所示。
0.11001=1*2^-1+1*2^-2+1*2^-5=0.5+0.25+1/32=0.75+0.03125=0.78125=25/32
再将一个二进制的小数转换为十进制
0.01011=1*2^-2 +1*2^-4 +1*2^-5 =0.25+0.0625+0.03125=0.34375=11/32
十进制的小数转换为二进制的小数使用重复相乘法来计算的。
下面以一个小数0.78125为例子,介绍转换二进制的过程。
0.78125转换为分数的形式就是25/32
重复乘以2 | 积 | 取1 |
---|---|---|
25/32 | 50/32=1+9/16 | 1 |
9/16 | 18/16=1+1/8 | 1 |
1/8 | 2/8=0+1/4 | 0 |
1/4 | 2/4=0+1/2 | 0 |
1/2 | 2/2=1+0 | 1 |
而后再将取1的结果从上到下串联起来,即0.78125转换为二进制的结果是0.11001
再计算一个小数0.34375,转换为分数形式为11/32,计算步骤以下所示
重复乘以2 | 积 | 取1 |
---|---|---|
11/32 | 22/32=0+11/16 | 0 |
11/16 | 22/16=1+3/8 | 1 |
3/8 | 6/8=0+3/4 | 0 |
3/4 | 6/4=1+1/2 | 1 |
1/2 | 2/2=1+0 | 1 |
而后再将取1的结果从上到下串联起来,即0.34375转换为二进制的结果为0.01011。
在十进制中使用加号(+)表示整数,使用减号(-)表示负数,那么负数在计算机中是如何表示的呢?
首先以正整数127(占1个字节)为例子,转换为二进制的结果是01111111,那么-127如何表示呢,结果是11111111,由于计算机在存储数据时,按照符号位和数字位组成,其中符号位是二进制数据的左边第一位数字,若是是0,则表示该数字是整数,例如01111111,若是是1表示该数字为负数,例如11111111,这样的表示方法就是原码表示法,原码表示法在表示数据时有以下特色:
前面在进行进制转换的使用使用的按权展开法,重复相乘法,重复相除法都是基于二进制原码表示法进行操做的。
可是原码表示法有有些缺陷,好比说在使用原码表示0的时候,这里以一个字节为例:0的正数表示为00000000,0的负数是10000000,无论正0和负0其实都是0,容易产生歧义。
原码表示法在进行数据计算的时候特别复杂,特别是两个操做数符号位不相同的时候,主要须要如下步骤:
引进补码的目的:
x>0, x=x
x<0,x=2^(n+1)+x
其中n表示二进制的位数,以一个字节为例,那么n就是8,若是是两个字节,那么n就是16,依次类推。
补码的计算案例
13的原码以一个字节表示就是00001101。
而13大于0,所以13的补码和原码同样,也就是00001101。
-13的原码为10001101,由于是负数,因此最高位为-1
而-13的补码能够根据公式x=2^n+1+x
x=2^(8+1)+ -13=512-13=499=1 1111 0011
而 1 1111 0011已经超出了一个字节表示的数据范围(-128-127),因此须要将最左边的1截取掉,所以-13的补码结果为1111 0011。
x=2^(n+1)+x
x=2^(n+1)+x=2^9+ -7=512-7=505=1 1111 1001
一样的道理,1 1111 1001超过了一个字节的表示范围(-128-127),因此须要将最左边的1截取掉,即-7的补码表示为11111001。
x=2^(n+1)+x
x=2^(8+1)+ -1=512-1=511=1 1111 1111
一样的道理,1 1111 1111超过了一个字节的表示范围(-128-127),因此须要将最左边的1截取掉,即-1的补码表示为11111111。
以上的例子在计算补码的过程当中仍是使用了减法实现计算。
反码出现的目的就是找出原码和补码的规律,消除转换过程当中的减法。
反码的计算公式以下所示
x>0, x=x
x<0,x=(2^(n+1)-1)+x
反码计算案例
-13的原码是1000 1101
-13的反码能够根据公式x=(2^(n+1)-1)+x
x=(2^(8+1)-1)+ -13=511-13=498=1 11110010
因为1 11110010超过了一个字节的表示范围(-128-127),因此须要将最左边的1截取掉,即-13的补码表示为11110010。
2.x=-7,n=8,计算x的原码和反码
-7的原码为10000111
-7的反码能够根据公式x=(2^(n+1)-1)+x
x=(2^(8+1)-1)+ -7=511-7=504=1 11111000
因为1 11111000超过了一个字节的表示范围(-128-127),因此须要将最左边的1截取掉,即-7的反码表示为1111000。
这里采用一个字节存储,总结下以前使用过的十进制整数7,-7和13,-13的原码、补码、反码
十进制 | 原码 | 补码 | 反码 |
---|---|---|---|
7 | 7 | 7 | 7 |
-7 | 10000111 | 11111001 | 1111000 |
13 | 13 | 13 | 13 |
-13 | 1000 1101 | 1111 0011 | 11110010 |
根据以上表格的数据能够获取到如下结论
根据规律计算原码、反码和补码的案例
1.x=-7,求原码、反码和补码
-7的原码是1000 0111,反码是1111 1000,补码是1111 1001
2.x=-9,求x的原码、反码补码
-9的原码是100001001,反码是111110110,补码是11110111
原码、补码、反码总结:
因为原码存在着表示0有歧义,减法运算复杂的问题,所以引进了补码解决了这俩问题,可是在原码转换为反码的计算过程当中仍是使用了减法,所以引进了反码则是消除了原码计算补码时须要使用减法,原码转换为反码只须要最高位不变,其余位取反便可,而反码转换为补码只须要在反码的基础上加1便可,源码计算反码经过先求反码,再求补码消除了减法。
首先回顾下整数的二进制补码表示法的计算公式
x>0, x=x
x<0,x=2^(n+1)+x
而小数的二进制补码表示法的计算公式以下所示
x>0, x=x
x<0,x=2+x
小数的二进制补码计算案例
重复乘以2 | 积 | 取1 |
---|---|---|
9/16 | 18/16=1+1/8 | 1 |
1/8 | 2/8=0+1/4 | 1 |
1/4 | 2/4=0+1/2 | 0 |
1/2 | 2/2=1+0 | 1 |
即9/16的二进制转换结果为0,0.1101,默认的转换结果为原码表示,由于9/16是正数,所以其二进制的原码、反码和补码都是0,0.1101。
重复乘以2 | 积 | 取1 |
---|---|---|
11/32 | 22/32=0+11/16 | 0 |
11/16 | 22/16=1+3/8 | 1 |
3/8 | 6/8=0+3/4 | 0 |
3/4 | 6/4=1+1/2 | 1 |
1/2 | 2/2=1+0 | 1 |
即-(11/32)的二进制转换结果为1,0.01011,默认的转换结果为原码表示,还须要求x的反码和补码,x的反码是1,1.10100,x的补码是1,1.10101。
定点数的表示方法:定点数就是小数的固定在某个位置的数。
定点数有两种表示方法,第一种是小数点在符号位和数值位数的中间,这种被称为纯小数,以下表格所示
数值 | 符号位 | 数值位 |
---|---|---|
0.1011 | 0 | 1011 |
-0.1011 | 1 | 1011 |
第二种是小数点在数值位的最后面,这种被称为纯整数,以下表格所示
数值 | 符号位 | 数值位 |
---|---|---|
1011 | 0 | 1011 |
1011 | 1 | 1011 |
若是想要表示的数据不是纯整数也不是纯小数,此时必须乘以比例因子以知足定点数保存格式,例如二进制10.01能够经过将小数点左边移两位知足纯小数的表达方法,或者经过将小数点右边移动两位知足纯整数的表达方法。
首先明确浮点数的由来,由于计算机常常处理的数据绝大部分都不是纯小数或者纯整数,并且当数据的范围很大,难以用定点数表示,而且定点数不够灵活,所以出现了浮点数。
浮点数的表示形式
为了了解浮点数的表现形式,首先回一下学校学过的科学计数法。
例如整数123450000使用科学计数法表示为1.2345*10^8
,其中1.2345表示尾数,10表示基数,8表示的是阶码,在浮点数的表示格式中也存在尾数、基数和阶码的概念。
对于任意的浮点数均可以使用以下公式转换
N=S*r^j
其中S表示尾数,r表示基数,j表示阶码。
例如二进制小数 11.0101=0.110101210,须要指出的是210的10指的是2的二进制表示方式,并非十进制的10
11.0101还能够表示为0.0110101211,须要指出的是211的11指的是3的二进制表示方式,并非十进制的11。
在计算机内部,浮点数的存储包含四部分,分别是 阶码符号位、阶码数值位、尾数符号位、尾数数值位,由于阶码和尾数多是负数,因此有符号位,并且浮点数的尾数必须是纯小数。
例如二进制的11.0101按照不一样的阶码在内存的存储方式为
11.0101=0.1101012^10 阶码为二进制的10
11.0101=0.01101012^11 阶码为二进制的11
二进制浮点数数值 | 阶码符号位 | 阶码数值位 | 尾数符号位 | 尾数数值位(8位) |
---|---|---|---|---|
0.110101*2^10 | 0 | 10 | 0 | 11010100 |
0.0110101*2^11 | 0 | 11 | 0 | 01101010 |
因为这里的尾数数值必须知足8位,若是不足8位,须要用0补足。
因为浮点数是由阶码和尾数组成,所以考虑浮点数的表示范围实际上就是阶码和尾数的取值范围。
这里方便理解假设阶码的数值有m位,尾数的数值有n位,对于任意一个浮点数,阶码表示的最大值就是2^m-1
,假设阶码有8位而且全是1,那么这个阶码表示的最大值就是255,若是考虑符号位,那么阶码的取值范围就是-(2^m-1) - 2^m-1
,那么8位数阶码的取值范围就是-255 - 255
。
尾数要求是纯小数,尾数能表示的最大值1-2^-n
,尾数所能表示的最小值2^-n
,所以尾数的表示范围是2^-n - 1-2^-n
,若是考虑符号位,尾数的取值范围是
负数:-(1-2^-n) - -(2^-n)
正数: 2^-n - 1-2^-n
因此浮点数表示的最小负数值是-(1-2^-n)*2^(2^m-1)
,最大的负数是-(2^-n)*2^-(2^m-1)
。
浮点数表示的最大的正数值是(1-2^-n)*2^(2^m-1)
,最小的正数值是(2^-n)*2^-(2^m-1)
。
若是超过了浮点数表示的最大值则会发生数据溢出,称为上溢(数值太大)。
若是超过了浮点数表示的最小值则会发生数据溢出,称为下溢(数值过小)。
平常开发中常用单精度和双精度浮点数,其中单精度是使用4个字节即32位存储的浮点数
而双精度是使用8个字节即64位存储的浮点数。
首先回到以前的科学计数法的例子:123450000=1.2345*10^8,
科学计数法规定了尾数必须在1-10之间,例如12345 000 0000=12.345*10^10
,12.345超过了尾数的范围则会不符合要求。
一样在浮点数中的尾数也有相关的要求
符合浮点数规格化的表示方法案例
11.0101=0.110101*2^10
尾数的最高位不是1,不符合规范
11.0101=0.0110101*2^11
尾数的最高位不是1,不符合规范
11.0101=0.00110101*2^100
尾数不是纯小数,不符合规范
11.0101=1.10101*2^1
浮点数阶码与尾数的案例
1.假设浮点数字长16位,尾数为11位,阶码为5位,将十进制数13/128表示为二进制的浮点数
首先明确这里的浮点数由1位尾数符号位加上10位尾数数值加上1位阶码符号位加上4位阶码数值组成。
而后将十进制数13/128转换为浮点数,计算过程以下所示
重复乘以2 | 积 | 取1 |
---|---|---|
13/128 | 26/128=0+13/64 | 0 |
13/64 | 26/64=0+13/32 | 0 |
13/32 | 26/32=0+13/16 | 0 |
13/16 | 26/16=1+5/8 | 1 |
5/8 | 10/8=1+1/4 | 1 |
1/4 | 2/4=0+1/2 | 0 |
1/2 | 2/2=1+0 | 1 |
十进制13/128转换为二进制的原码结果是0.0 001 101 000
,因为正数的原码、反码、补码同样,这里不须要转换成补码。然后面的三个0是为了知足尾数数值为10位的要求
再按照规格化的要求转换浮点数,向左移动3位(乘以2的-3次方)便可知足尾数最高位必须是1
0.0001101000=0.1101000*2^-11,其在计算机的存储格式以下表格所示
数值 | 阶码数值 | 阶码符号 | 尾数数值 | 尾数符号 |
---|---|---|---|---|
0.1101000*2^-11 | 0011 | 1 | 1101000000 | 0 |
2.假设浮点数字长16位,尾数为11位,阶码为5位,将十进制数-54表示为二进制的浮点数
首先明确这里的浮点数由1位尾数符号位加上10位尾数数值加上1位阶码符号位加上4位阶码数值组成。
而后将-54转换为二进制,-54的原码表示方式为1,11 0110,逗号左边的1表示为负数,而后再将110110按照浮点数规格化的要求转换110110=0.110110*2^110
而后再按照16位浮点的字长转换
首先是尾数为10位,即110110转换成110110 0000,转换以后的反码为001001 1111,尾数的补码是00101 0000 ,,因为尾数补码的最高位是0,所以尾数符号的结果就是1。
尾数肯定以后就能够计算阶码,阶码符号是0,由于阶码是正数,而阶码数值是0110,由于要知足接码数值的位数是4位,最后就能够计算出来-54在计算机中是如何存储的了
数值 | 阶码数值 | 阶码符号 | 尾数数值 | 尾数符号 |
---|---|---|---|---|
0.110110*2^110 | 0110 | 1 | 00101 0000 | 0 |
须要注意的是,计算机的数据最终是以补码的方式存储的。,所以这里的尾数数值取得是补码的结果
定点数的加法分为整数部分和小数部分,例如两个定点数A和B相加
整数加法: A的补码+B的补码=(A+B)的补码(mod2^n+1)
小数加法: A的补码+B的补码=(A+B)的补码(mod2)
在实际运算时,数值位与符号位一同参与运算,并将符号位产生的进位天然丢掉,也就是(mod2^n+1)和(mod2)的操做。
这里先列出原码以及反码的计算公式
原码=补码取反加1
补码=原码取反加1
定点数的加法运算案例:
1.假设 A=-110010, B=001101,求A+B
首先求A -110010的补码 求反码结果是001101,求补码的结果是1,001110,其中最左边的1表示符号位。因为B是正数,所以B的补码就是B的原码,也就是001101。
符号位与数值位计算过程
A+B=A的补码+B的补码=(A+B)的补码(mod2^n+1)=1,011011=-100101
1,001110
0,001101
1,011011
1,0111011 表示为补码,还须要转换为原码,补码首先减去1求反码的结果是1,011010,反码求原码的结果是100101,即最终A+B的结果是-100101。
2.假设A=-0.1010010,B=0.0110100,求A+B的和
首先求出A的补码,1,0.1010010的反码是1,1.0101101,补码是原码末位加1,结果为1,1.0101110
因为B的最高位是0,所以B的补码是0.0110100。
符号位与数值位一同计算的过程
1,1.0101110
0,0.0110100
1,1.1100010
A+B=A的补码+B的补码=1,1.0101110+0,0.0110100=1,1.1100010
而后将补码1,1.1100010求反码的结果是1,0.0011101,再将末位加1,求原码结果为1,0.0011110,也就是A+B的最终结果是-0.00111100
3.A=-10010000,B=-01010000,求A+B的和
首先计算出A的补码,即原码取反加1的结果为1, 01110000
而后再计算忽B的补码,即原码取反加1的结果为1,10110000
而后再将符号位和数值位一同参与运算,计算过程以下
1,0111 0000
1,1011 0000
11,0010 0000
因为数值位和符号位一同运算时发生了进位,此时符号位产生的进位天然丢掉
即A+B=A的补码+B的补码=1,01110000+1,10110000=1,0010 0000
1,00100000的反码是1,11011111,而后在末位加1,即A+B的结果是-11100000
4.A=-10010000,B=-11010000,求A+B的和
首先计算A的补码1,10010000取反的结果是1,01101111,而后加1的结果是1,01110000。
而后计算B的补码1,11010000取反的结果是1,00101111,而后加1的结果是1,00110000。
即A+B=A的补码+B的补码=1,01110000+1,00110000
而后再将符号位和数值位一同参与运算,计算过程以下
1,01110000
1,00110000
10,10100000
因为数值位和符号位一同运算时发生了进位,此时符号位产生的进位天然丢掉
所以A+B=A的补码+B的补码=1,01110000+1,00110000=0,10100000,因为最高位是0,所以A+B的原码和补码一致,也就是A+B的最终结果是10100000。
负数和负数相加的结果应该是负数,可是这里的结果10100000是正数,显然结果是不正确的,这里咱们将二进制的运算数据转换为十进制相加,即-144+ -208=-352,正确的运算结果的十进制值是-352。
由于这里发生了溢出现象,咱们使用1个字节的数值存储了-352,超过了它的表示范围。
咱们能够采用双符号位判断法来判断数据在运算的过程当中是否发生了溢出现象。
所谓的双符号位判断法就是将原来用单符号位表示成双符号位,即0换成00,1换成11,并且在运算过程当中,双符号位运算所产生的进位也会丢弃,而结果的双符号位不一样则表示溢出,一旦发生了溢出现象也就意味着计算结果是不正确的。
双符号位判断法的案例
1.A=-10010000,B=-11010000,使用双符号位求A+B的和
首先计算A的补码1,10010000取反的结果是1,01101111,而后加1的结果是1,01110000。
而后计算B的补码1,11010000取反的结果是1,00101111,而后加1的结果是1,00110000。
即A+B=A的补码+B的补码=1,01110000+1,00110000
而后再将符号位和数值位一同参与运算,计算过程以下
11,01110000
11,00110000
1 10,10100000
因为数值位和符号位一同运算时发生了进位,此时符号位产生的进位天然丢掉
所以A+B=A的补码+B的补码=11,01110000+11,00110000=10,10100000,因为双符号位不一样,表示溢出,所以计算结果是错误的。
2.A=-10010000,B=-01010000,使用双符号位求A+B的和
首先计算出A的补码,即原码取反加1的结果为11, 01110000
而后再计算忽B的补码,即原码取反加1的结果为11,10110000
而后再将符号位和数值位一同参与运算,计算过程以下
11,0111 0000
11,1011 0000
1 11,0010 0000
因为数值位和符号位一同运算时发生了进位,此时符号位产生的进位天然丢掉
即A+B=A的补码+B的补码=11,01110000+11,10110000=11,0010 0000,因为11表示双符号相同,即计算结果为没有溢出。
11,00100000的反码是11,11011111,而后在末位加1,即A+B的结果是-11100000
定点数的减法运算也分为整数减法和小数减法两个部分,例如两个定点数A和B相减法有以下公式。
整数减法:A的补码-B的补码=(A+ -B)的补码(mod2^n+1)
小数减法:A的补码-B的补码=(A+ -B)的补码(mod2)
减法运算实际上仍是转换成了加法运算,即减去一个数等于加上这个数的负数,而-B的补码等于 B的补码连同符号位按位取反,末位加1。
例如B的补码等于1,0010101,那么-B的补码就是0,1101011。
定点数减法运算案例
A=11001000,B=-00110100,求A-B
首先求A的补码,因为A是正数,所以A的补码是0,11001000
由于A-B= A+ -B
因此先求出B的补码,1,00110100的反码是1,11001011,而后再加1的结果是1,11001100。
而后再求出-B的补码0,00110100。
所以A-B=11001000+00110100
00,11001000
00,00110100
00,11111100
即A-B=11111100
首先使用x,y分别表示两个浮点数,根据以前学习的浮点数表示法知道
对于任意一个浮点数,均可以使用N=S*r^j
来表示,所以x,y分别使用以下形式表示。
x=S * r^j y=S * r^j
其中S表示尾数,r表示基数,j表示阶码。
对于一个浮点数的加减运算,会经历以下5个步骤
对阶的目的就是使得两个浮点数的阶码一致,使得尾数能够进行运算,由于浮点数的尾数运算实际上就是以前学习的定点数运算,相对简单。可是浮点数位数的实际小数位阶码有关,若是阶码不对阶则没法进行浮点数的运算,而对阶的阶码则会按照小阶看齐大阶的原则。
例如二进制x=0.1101*2^01,y=(-0.1010)*2^11
,在计算机中的存储以下表格所示,其中符号位使用双位符号位存储,而数值位使用4位存储。
对阶以前的存储
数值 | 阶码符号位 | 阶码数值位 | 尾数符号位 | 尾数数值位 |
---|---|---|---|---|
x | 00 | 00 01 | 00 | 1101 |
y | 00 | 0011 | 11 | 1010 |
小阶看齐大阶,也就是将x的阶码由01变成y的阶码11,x的尾数右边移动两位,左边补上00,即x=0.001101*2^11,y=(-0.1010)*2^11
,因为尾数按4位存储,所以舍去x的尾数0.001101的最后两位数01。
小阶看齐大阶以后x,y在计算机中的存储
数值 | 阶码符号位 | 阶码数值位 | 尾数符号位 | 尾数数值位 |
---|---|---|---|---|
x | 00 | 0011 | 00 | 0011 |
y | 00 | 0011 | 11 | 1010 |
尾数的求和 和定点数的加减法同样,使用补码运算,减法运算转换为加法运算,即A-B=A+(-B)。
在x,y完成对阶以后x=0.0011*2^11,y=(-0.1010)*2^11
。
首先求出二进制浮点数x,y 尾数的补码
二进制浮点数x尾数的原码为00.0011 ,二进制浮点数y尾数的原码为11.1010
根据(负数)反码=原码取反,末位加1,正数 原码=反码=补码的规则计算
二进制浮点数x尾数的补码为00.0011 ,二进制浮点数y尾数的补码为11.0110
将x和y的符号位和数值位一块儿运算获得尾数求和的结果 S=(x+y)[ 补码]=00.0011+11.0110=11.1001
数值 | 阶码符号位 | 阶码数值位 | 尾数符号位 | 尾数数值位 |
---|---|---|---|---|
x | 00 | 0011 | 11 | 1001 |
S>0 S[补码]=00.1xxx
S<0 S[补码]=11.0xxx
通常状况下,若是不知足上面的格式,须要进行左移,左移N位,浮点数尾数的末位补N个0,依次类推,同时阶码发生相应的变化,以知足规格化的要求。即若是尾数符号位和尾数最高位不一致的状况下须要进行尾数的规格化,若是双符号位不一致的状况下须要右移(定点运算溢出的状况),若是是右移的话则须要进行舍入操做。
尾数规格化以前:
S=(x+y)[补码]=`00.0011+11.0110=11.1001`
将11.1001左移一位,即将尾数的最高位1001的最左边的1舍弃掉,由于尾数数值位只考虑四位,而后在尾数的末位补上0,11.1001 规格化 左移1位的结果是 11.0010
尾数规格化以后:
S=(x+y)[补码]=`00.0011+11.0110=11.1001=11.0010
11.0010在计算机中的存储以下表格所示
数值 | 阶码符号位 | 阶码数值位 | 尾数符号位 | 尾数数值位 |
---|---|---|---|---|
x | 00 | 0010 | 11 | 0010 |
尾数左边移动N位,阶码数值位相应的减N位,例如这里x的尾数左移1位,阶码由原来的
0011变成了0010。
S=(x+y)[补码] =11.0010
计算机存储采用的是补码表示法,而咱们看到的数据都是使用原码表示法表示的,所以这里还须要将11.0010转换为原码。
而11.0010原码是11.1110,即-0.1110,因此x+y的结果是 -0.1110*2^10
正数的右移,负数的无符号右移,就是相应的补码移位所得,在高位补0便可。
负数的右移,就是补码高位补1,而后按位取反加1便可。
浮点数规格化时若是双符号位不一致的状况下须要右移,而右移动则须要进行舍入的操做,在操做十进制数据时有时候会进行四舍五入,而对于二进制是零舍一入,等效于十进制的四舍五入。
例如S[补码]=10.10110111
,因为双符号位是10,因此是双符号位不一致,此时须要进行右移操做,右移以后S[补码]=11.01011011(1)
,而后进行零舍一入,由于尾数最后面一位是1,所以尾数末位须要加1,即11.01011011+1=11.01011100,
右移的操做,若是考虑阶码的话,阶码也要加1,也就是S[ 补码]=10.10110111舍入操做的结果是11.01011100。
零舍一入能够提升尾数规格化的精度,可是零舍一入可能会发生溢出的状况
例如S[补码]=01.11111111,因为双符号位是01,所以须要进行右移规格化,采用零舍一入,由于最后面一位是1,所以尾数末位要加上1,即00.11111111+1=01.00000000,因为右移动一位以后双符号位是01,即双符号位仍然不一致,还须要进行右移动操做,01.00000000右移一位的结果是00.1000000(0),即S[补码]=01.11111111进行舍入操做后的结果是00.1000000。由于进行了两次右移操做,阶码还须要加10(即十进制的2)。
可是在浮点数运算时双符号位判断法并不适用,浮点数运算尾数双符号位不一致并不算溢出,由于当浮点数尾数双符号位不一致时能够右移把不一致的双符号位运算符变成一致。
在浮点数中的溢出判断主要是经过阶码的双符号位判断是否溢出,若是尾数规格化以后,阶码的双符号位不一致,则认为是溢出。
浮点数加减法运算的案例
例如 x=0.11010011*2^1101,y=0.11101110*2^1100
,假设阶码4位,尾数8位,计算x+y的结果
首先将x和y的值在计算机中的存储表示出来,以下表格所示
数值 | 阶码符号位 | 阶码数值位 | 尾数符号位 | 尾数数值位 |
---|---|---|---|---|
x | 00 | 1101 | 00 | 11010011 |
y | 00 | 1100 | 00 | 11101110 |
首先第一步进行对阶的操做,按照小阶对齐大阶的原则,由于1101>1100,因此须要将y右移动1位来完成对阶,y=0.011101110*2^1101
,而按照尾数是8位的要求对阶以后的结果以下表格所示
数值 | 阶码符号位 | 阶码数值位 | 尾数符号位 | 尾数数值位 |
---|---|---|---|---|
x | 00 1101 | 00 | 11010011 | |
y | 00 | 1101 | 00 | 01110111 |
因为x,y都是正数,所以x[补码]+y[补码]=x[原码]+y[原码]=00.11010011+00.01110111=01.01001010,计算过程以下所示,
x 00.11010011
y 00.01110111
01.01001010
尾数求和以后尾数的符号位结果是01,在定点数运算时算符号位不一致表示溢出,可是浮点数是根据阶码的双符号位判断是否溢出。
浮点数 x+y 尾数求和的结果是01.01001010,因为符号位不一致,所以进行右移操做,01.01001010 右移,即将01.01001010的最后一个0舍弃掉,而后把符号位补上一个0, 即01.01001010 右移1位的结果是 00.10100101
按照零舍一入的原则,00.10100101(0)舍入的结果是00.10100101,最终的结果以下表格所示
数值 | 阶码符号位 | 阶码数值位 | 尾数符号位 | 尾数数值位 |
---|---|---|---|---|
x+y | 00 | 1110 | 00 | 10100101 |
溢出判断是判断阶码的符号位,即判断00.10100101
00.10100101的阶码符号位为00,因此没有发生溢出,即x+y的最终结果是
x+y[原码]=x+y[补码]=0.10100101*2^1110
浮点数加减法的运算流程图
假设有两个浮点数x,y,能够采用以下表示方法
x=Sx*r^jx y=Sy*r^jy
对于浮点数的乘法运算是按照阶码相加,尾数求积来运算的,即xy=(SxSy)*r^(jx+jy)
对于浮点数的除法运算时按照阶码相减,尾数求商来运算的,即x/y=(Sx*Sy)*r^(jx-jy)
浮点数的乘除法运算是按照阶码运算->尾数运算->尾数规格化->舍入->溢出判断五个过程
例如二进制浮点数 x=0.11010011*2^1101
,y=0.11101110*2^0001
,假设阶码为4位,尾数8位,计算x*y
x*y=(0.11010011 *0.11101110)*2^(1101+0001)=0.11000100*2^1110
即阶码运算和尾数运算以后x*y的值是0.11000100*2^1110
,在计算机中存储以下表格所示
数值 | 阶码符号位 | 阶码数值位 | 尾数符号位 | 尾数数值位 |
---|---|---|---|---|
x*y | 00 | 1110 | 00 | 11000100 |