进位计数制
- 进制分类
- 二进制(前缀为 0b)
- 八进制(前缀为 0 )
- 十进制
- 十六进制(前缀为 0x)
- 进制转换
- 二进制,八进制,十六进制向十进制转换
- 二进制 》》十进制
每一位的二进制数 _ 该位数字的位权,例如:10101 = 1 *_ 24 + 0 *_ 23 + 1 *_ 22 + 0 *_ 21 + 1 *_ 20 = 21
- 八进制 》》十进制
每一位的八进制数 _ 该位数字的位权,例如:54643 = 5 *_ 84 + 4 *_ 83 + 6 *_ 82 + 4 *_ 81 + 3 *_ 80
- 十六进制 》》十进制
每一位的十六进制数 _ 该位数字的位权,例如:165A = 1 *_ 163 + 6 *_ 162 + 5 *_ 161 +10 * 20
- 二进制和八进制,十六进制之间相互转换
- 二进制 》》八进制
每三位数字转换成对应的八进制数字,例如:001 111 001 100 = 1714
- 二进制 》》十六进制
每四位数字转换成对应的十六进制数字例如:0001 1100 0101 0001 = 1C51
- 八进制 》》二进制
每个八进制对应 3 位二进制
- 十六进制 》》 二进制
每个十六进制对应 4 位二进制
- 十进制转换成任意进制
- 公式推导:
- (整数部分)每除一次基数 r ,都会得到余数 k0,也就是当前数的最低位,接着取余继续除基数,因此该方法也被称为除基取余法。
- (小数部分)每乘一次基数 r ,都会得到整数 k-1 ,也就是当前数的最高位,接着取整继续乘基数,因此该方法也被称为乘基取整法。
- 真值和机器数
- 真值:符合人类习惯的数字
- 机器数:数字实际存到计算机中的形式,正负号需要被“数字化”
- 例如:真值为 15 和 -8 的数字存放到计算机中就是二进制数字 0 1111 和 1 1000 其中的最前面的数字代表符号位
BCD码
- 前面我们学习的二进制和十进制码之间的转换过于麻烦,为了快速的转换,我们可以使用 BCD 码(BInary-Coded Decimal),每个十进制我们都用 4 位二进制数字表示。
- 第一种:8421 码的映射关系(每一位的权值分别是 8 4 2 1 )
当我们进行计算时,例如 3 + 3 就是 0011 + 0011 = 0110 ,对应了 8421 码中的十进制数字 6 。但是当我们相加的数字超过十进制的 9 时,我们会发现无法用 8421 码进行表示,此时我们需要加六,也就是 0110 ,从而实现进位。例如 8 + 5 = 1000 + 0101 = 1101。我们将其加上 0110 得到 0001 0011 也就是十进制的 13。
- 第二种:余 3 码(8421 码 + (0011) )
- 第三种:2421码
为了避免歧义,我们将 0 - 4四个数字的最高位固定为 0,5 - 9 的为高位固定为 1。
无符号整数的定义和运算
- 该计算机硬件支持的无符号整数位数有上限,假如机器的字长只有 8 位,那么通用寄存器的存储位数就只有 8 位,也就代表我们最多同时进行8 位的运算。当然我们现在的个人计算机机器的字长通常都是 64 位或者至少 32 位。
- 定义
- 全部二进制位都是数值位,没有符号位,第 i 位的位权是 2i-1
- n bit 无符号位整数的表示范围是 0 ~ 2n-1,超出会造成溢出,意味着计算机一次无法处理这些数据
- 可以表示的最小的数是全 0 ,可以表示最大的数是全 1
- 运算
- 加法 : 从最低位开始,按位相加,向更高位进位
- 减法 : 被减数不变,减数全部按位取反,末尾加1,减法变加法,按照加法规则进行相加,注意我们在使用 99 - 9 时,99 是被减数,9 是减数. (不需要深究为什么这样操作)
带符号整数的定义和运算
- 原码,反码,补码
- 符号位"0/1"对应表示"正/负",剩余的数值位表示真值的绝对值.
- 假设机器字长的位数是 n+1 位,带符号位的原码的表示范围是 : -(2n-1) <= x <= 2n-1
- 真值0有两种方式: +0 和 -0,[0]原 = 0,0000000, [-0]原 = 1,0000000 (上述书写方式属于书面写法)
- 在进行运算时,由于计算机需要复杂的电路对符号位进行判断,因此使用补码对其进行运算.
- 由于补码转换成反码需要通过末位减 1 的复杂转换,我们可以先将其转换成原码,在转换成反码
- 当我们进行减法运算时,为了将减法运算变成加法运算,[A]补 - [B]补 = [A]补 + [-B]补因此我们需要将减数的补码转换成其负值的补码.(我们也可以使用从右向左数,从第一个1开始,左边所有位包含符号位全部都取反)
- 移码
- 移码在补码的基础上进行符号位取反,只可以表示整数,同时要注意移码的真值0只有一种表示形式,同时移码整数的表示范围和补码相同
- 特性对比
原码和反码的合法表示范围完全相同,都有两种方法表示真值 0 ,补码和移码的合法表示范围比原码多出一个负数,且只有一种方法表示真值 0 ,关于补码的数值计算可以使用 -1 * 符号位数值 * 权重 + 每一位的数值 * 权重。
关于补码,原码,反码的理解可以参考下面的文章:
原码、反码和补码之间符号位改变的特殊情况分析(正零+0,负零-0,)_反码+1时进位怎么办-CSDN博客
关于 -128 ,+128,-0,+0,-1 的反码补码 - 今天还是要喝水 - 博客园
定点小数
- 定点数包含定点整数(带符号整数),定点小数
- 两者之间的区别在于隐含小数点的默认位置
- 原码表示
- 书写时定点小数常常使用符号位加 . 表示
- 比较
- 我们在进行位数扩展时,同时要注意扩展的位置不同。
我们需要根据小数点的位置进行判断,防止造成数值的改变
- 计算
在进行加法运算时,从最低位开始,按位相加(符号位参与运算),向更高位进位,多出的数直接舍弃
奇偶校验码
- 由于在进行传输中可能会出现位错误,将 1 转换成 0 ,我们在需要传输的数据中加上冗余字段作为校验码
- 定义
- 奇校验码:整个校验码(有效信息位和校验位)中的“1”的个数为奇数
- 偶校验码:整个校验码(有效信息位和校验位)中的“1”的个数为偶数
- 例如:对于 1001101 分别求奇偶校验码,设最高位为校验位,其余 7 位为信息位
由于 1001101 的 1 的个数为 4 个,因此它的奇校验码是在最高位加上一个 1,使其成为奇数 5,偶数校验码是在最高位加上一个 0 ,加上 0 使其个数保持为偶数 4。
- 偶校验的计算机硬件实现
对于所有的二进制位进行异或运算(模2加),例如 01001101 的运算就是 0 ^ 1 ^ 0 ^ 0 ^ 1 ^ 1 ^ 0 ^ 1 = 0,如果为 0 就是正确的
- 缺陷
这种校验机制存在一定的缺陷,当两个数发生错误时,无法进行正确校验
电路基本原理及加法器设计
- 最基本的逻辑运算
- 在门电路中,与门中如果我们是输入一个 5 v的高电平和一个 1 v的低电平,那么结果就是 1 v的低电平,如果是两个 5 v的高电平,那么结果也就是 5 v的高电平。
- 与运算的优先级高于或运算,类比于乘法和加法。
- 复合逻辑
- 加法器设计
- 一位全加器
当我们在进行上述的加法运算中,首先将加数和被加数设为Ai和Bi,将改位的进位设为Ci-1,接下来对于输出值(本位的和)Si和本位的进位进行讨论
我们的输入值为Ai,Bi,Ci-1,输出值Si也就是将所有输入值相加。输出值Ci的来源有两种,第一种,当本位都为1时,会发生进位。第二种,当本位中有一个1,但是低位的进位中还有一个1。将这两种情况进行或运算可以得到进位结果。
对于硬件的实现如上图所示,左侧是具体的实现方式,可以类比为一个函数的具体实现步骤,右侧是简化图,类比成一个函数的对外暴露接口。
- 串行加法器
仅使用一个全加器,数据逐位串行的送入加法器中进行运算,使用进位触发器存储信号,来参与下一次运算。
- 并行加法器
- 串行进位的并行加法进位器
将n个全加器串接在一起,可以进行两个n位数的加法运算。
但是由于高位的相加需要低位的进位数,因此这种加法器还是逐级相加的。
- 并行进位的并行加法进位器
这种并行的并行加法器,其中的各级信号同时形成,因此也称为先行进位,同时进位。
根据上面式子,我们可以看到当进行一个运算时,我们会用到之前的所有Gi和Pi的值,当我们计算C4的时候实际上需要的值已经被提供,因此我们可以进行并行的操作。
同时随着数据的位数不断地扩大,需要的表达式也会越来越复杂,因此需要的电路设计也会越来越复杂,因此我们通常到四位就会停止,设计一个4位的CLA加法器。
补码加减运算器
- 加法器原理
上图所示的加法器可以用来处理多位数之间的加法运算,与上面的一位全加器原理相同,只不过处理的位数不同。
- 补码加/减法运算方法
- n位补码相加,按位相加即可
- n位补码相减,将减数全部按位取反,末位加 1 。
产生进位时,需要丢掉最高位。其实丢弃最高位的过程就是对这个数的模的取余的过程,例如上面的-8-7得到的是10001,不考虑符号位也就是17,但是由于这是一个4bit的数,超过了范围,因此需要对16取模也就是最后的结果1,也就是0001。
- 加法器实现
- 当进行加法运算时,Sub 控制信号为 0 ,意味着多路选择器为 0 ,右边被接通,同时 Cin 中的输入为 0 ,整个程序仅仅实现 X 和 Y 的按位相加。
- 当进行减法运算时,Sub 控制信号为 1,意味着多路选择器为 1,左边被接通进行按位取反,同时 Cin 中的输入为 1,整个程序实现了 X + (-Y)的运算。
加减运算和溢出判断
- 原码的加减运算
- 原码的加法运算
- 正+正:绝对值做加法,结果为正
- 负+负:绝对值做加法,结果为负
- 正+负:绝对值大的减绝对值小的,符号同绝对值大的数
- 负+正:绝对值大的减绝对值小的,符号同绝对值大的数
2. 原码的减法运算 - 减数符号取反,转换为加法
- 补码的加减运算
对于补码来说,无论是加法还是减法,最后都会转换成加法,由加法器实现运算,符号位也参与运算。
- 溢出判断
- 设一个机器字长为 8 位(含一位符号位),那么它补码的范围就是 -128 到 127。
只有”正数+正数“才会上溢 – 正 + 正 = 负
只有”负数+负数“才会下溢 – 负 + 负 = 正
- 方法一:采用一位符号位
设 A 的符号为As,B的符号为Bs,运算结果的符号为Ss,则溢出逻辑表达式为
若 V = 0,表示无溢出
若 V = 1,表示有溢出
当以上两种情况出现会发生溢出现象,也就是当出现 正 + 正 = 负 和 负 + 负 = 正的现象。
- 方法二:采用一位符号位,根据数据位进位情况进行判断
根据判断Cs和C1是否相同来判断是否发生进位。V = Cs ^ C1,通过异或可以进行判断。
其中C1代表最高数值位的进位,Cs代表符号位的进位。
- 方法三:采用双符号位
正数符号为00,负数符号为11
按照上图,第一种情况可以看到前面应该是00,但是舍去了一个0,本身是正数但是结果为负数因此为上溢。第二种情况可以看到前面应该是11,但是舍去了一个1,本身是负数但是结果为正数因此为上溢。
设两个符号位为Ss1,Ss2,则 V = Ss1 ^ Ss2,若 V = 1,表示有溢出,V = 0,表示无溢出。
补充:
双符号位补码也称:模4补码
单符号位补码也称:模2补码
意为从符号位末位开始为20,到22,双符号位舍去大于等于4的位数,单符号位舍去大于等于2的位数。
实际上双符号位补码在存储中仅仅存储一个符号位,运算时会复制另外一个符号位。
- 符号扩展
- 定点整数
在原符号位和数值位之间添加新位,正数添加0,负数原码添加0,负数反码,补码添加1
- 正整数
0,1011010 >> 0,00000000 1011010
- 负整数
- 原码 :1,1011010 >> 1,00000000 1011010
- 反码 :1,1011010 >> 1,11111111 0100101
- 补码 :1,1011010 >> 1,11111111 0100110
其中原码直接补零,反码与原码数值位全取反,补码按照之前的规则,从右向左数找到第一个 1 ,该数的左边和反码一样,右边及其本身和原码一样。
- 定点小数
在原符号位和数值位后面添加新位,正数添加0,负数原码,补码添加0,负数反码添加1
- 正小数
0.1011010 >> 0.1011010 00000000
- 负整数
- 原码 :1.1011010 >> 1.1011010 00000000
- 反码 :1.1011010 >> 1.0100101 11111111
- 补码 :1.1011010 >> 1.0100110 00000000
标志位的生成
- OF(Overflow Flag)
含义:判断有符号数的加减运算是否发生溢出,OF = 1 时,说明发生溢出。
硬件计算方式:OF = 最高位产生的进位 ^ 次高位产生的进位
注意:该方法对于无符号的判断无效
- SF(Sign Flag)
含义:有符号位数加减运算的正负性,SF = 0 表示运算结果为正数,SF = 1 表示运算结果为负数。
硬件的计算方式:SF = 最高位的本位和
注意:该方法对于无符号的判断无效
- ZF(Zero Flag)
含义:表示运算结果是否为 0 ,ZF = 1 表示运算结果为 0 ,ZF = 0 表示运算结果为非0
硬件计算方式:两个数的计算结果全为 0 时,ZF 结果为 1。
- CF (Carry Flag)
含义:表示无符号数的加减法是否发生进位或借位,当 CF = 1,说明发生了进位或借位,也就是发生了溢出。
硬件计算方式:CF = 最高位产生的进位 ^ sub (sub = 1 表示减法,sub = 0 表示加法)
关于四个标志位的实现原理参考下面的链接
聊聊运算状态标志位CF_OF_SF_ZF的底层实现_哔哩哔哩_bilibili
定点数的移位运算
- 算数移位
- 原码的算数移位:符号位保持不变,仅对数值位进行移位。
右移:高位补0,低位舍弃。若舍弃的位 = 0,相当于 / 2,若舍弃的位 != 0,会造成精度的丢失。
左移:低位补0,高位舍弃。若舍弃的位 = 0,相当于 * 2,若舍弃的位 != 0,会造成严重的误差。
- 反码的算数移位:
正数的移位与原码相同。
负数的移位由于数值位与原码相反,规则如下。
右移:高位补1,低位舍弃。
左移:低位补1,高位舍弃。
- 补码的算数移位
正数的移位与原码相同。
由于负数的补码由于从左向右数第一个 1 的左侧与反码相同,该数及其右侧与原码相同。
右移:高位补1,低位舍弃
左移:低位补0,高位舍弃
- 逻辑移位
- 定义:进行右移,高位补0,低位舍弃;进行左移,低位补0,高位舍弃。相当于无符号数的移位。
- 应用:例如我们需要表示一个颜色编码 102 139 139
我们可以采用逻辑移位的方式进行存储。
对于这三个数值我们可以进行分别存储,最后再相加。
- 循环移位
- 当我们在进行一个 8 bit的运算时,可能会产生进位,但是由于机器字长有限,因此我们只好把进位存储在 CF 这个进位位中,方便带入下一轮的运算。
- 在进行循环左移中,我们会将进位位的数据放到末尾,同时将最高位的数据放到进位位。
采用循环移位可以很方便的将高字节和低字节之间进行互换。
乘法运算
- 手算乘法
按照每一位都是数值乘以每一位的位权的方式,我们可以将乘数按位展开,然后分别乘上被乘数。
对于这个式子我们可以参考十进制的乘法方式。
对于上面的权值计算,我们可以使用移位的方式进行运算。
- 原码一位乘法
设机器字长为 n + 1 = 5 位(含一位符号位),[x]原 = 1.1101,[y]原 = 0.1011,采用原码一位乘法求 x*y。
其中对于符号位我们可以单独使用异或处理,对于数值位取绝对值采用乘法进行处理。
对于一个乘法运算器,我们需要使用到 ACC 进行存储乘积高位,MQ 存储乘数和乘积低位,X 存储被乘数。
首先需要就 ACC 初始化为全 0,接着从 MQ 中的乘数最低位开始进行运算,当前位为 1 ,则在 ACC 上加上被乘数。
在进行第二次运算时,先将 MQ 和 ACC 中的数全部右移,接着加上被乘数和当前位的运算结果。
最后得到的结果为下图所示
最后我们对符号位进行异或处理,将得到的结果替换当前的符号位。
- 补码的一位乘法
补码的乘法规则类似于原码:
- 辅助位 - MQ 中的最低位 = 1,(ACC)+ [x]补
- 辅助位 - MQ 中的最低位 = 0,(ACC)+ 0
- 辅助位 - MQ 中的最低位 = -1,(ACC)+ [-x]补
由于 MQ 中的位数为 n+ 2 因此会将 ACC 和 X 中存放的数转换为双符号位(n+2)。
需要注意的是,再进行了 n 轮的运算之后需要在进行一次乘法,但是不需要进行移位。
区别:
- 在原码运算中,每次加法可能是0,[ |x| ]原,在补码运算中,加法可能是0,[x]原,[-x]原。
- 在原码运算中,每次移位是“逻辑右移”,再补码运算中,每次移位是“补码的算术右移”,需要参考符号位。
- 在原码运算中,乘数的符号位不参与运算,再补码运算中,由于在 n 轮运算后还需要进行一次运算,因此需要用到乘数的符号位。
- 补码运算中由于符号位参与了运算,因此不需要根据异或进行判断符号位。
除法运算
- 手算除法
由于被除数 = 除数 * 商 + 余数
我们可以先忽略小数点,然后每确定一位商,进行一次减法,得到四位余数,再得到下一位商,直到得到五位商为止(机器字长为 5 位)
- 原码除法:恢复余数法
在进行运算时,首先我们会从商的最低位开始确认,由于计算无法判断是需要 1 还是 0 ,因此会先默认为 1 ,如果得到的结果的符号位为 1 表示负数,意味着应该取 0 。同时将被改变的余数加上除数得到之前未改变的值,该方法也称为恢复余数法。
在得到第一次的结果后,由于下一次的运算需要进行错位相减,因此需要 ACC,MQ 中的数整体左移,空位使用 0 补全。
按照这样的方法继续确定商的值,需要注意的是由于进行了逻辑左移(高位舍弃,低位补 0 ),因此我们每一次确定的商的位数都是最低位。
最后由于是定点小数,小数点隐藏在符号位后面,因此我们可以得到商的值为 0.1101 ,而对于余数还需要在此基础上 * 2-n,同时通过对除数和被除数的符号位进行异或操作,确认商的符号位。
注意:余数的符号位和商的符号位是相同的。
- 原码除法:加减交替法
在上面的恢复余数法中,恢复余数这个过程过于麻烦,因此按照上面的数学推导,我们可以先进行左移,在加上除数,该方法也被称为加减交替法。
注意:
- 虽然该方法也被称为不恢复余数法,但是如果在最后得到的余数为负数,那么应该加上除数进行回复余数。最后根据异或判断符号位,需要注意的是余数的符号位和商的符号位一定是相同的。
- 这些方法进行的都是定点小数的计算,如果被除数大于除数的话,无法进行表示,因此我们可以通过第一次确定商时进行判断,如果是 1 的话也就意味这个被除数大于除数,硬件电路会检测到该问题,并且直接停止运算。
- 补码除法:加减交替法
- 符号位参与运算
- 被除数,除数,余数均采用双符号位的方式进行存储。
步骤:
- 首先如果被除数和除数同号,被除数减去除数。如果异号,被除数加上除数。
- 接着如果余数和除数同号,商为 1 ,余数左移一位并且减去除数。如果余数和除数异号,商为 0 ,余数左移一位并且加上除数。
- 将上面一步重复 n 次。
同时在最后一步中不需要考虑除数和余数的符号是否相同,将末位商设为 1 即可,这样可以方便运算。
注意:在最后的余数中,我们需要使其 * 2-n,并且由于符号位参加了运算,因此不需要进行异或判断。
区别辨析:
C语言强制类型转换
- 对于无符号数和有符号数之间的转化,不改变数值本身,改变数值的解释方式。
- 对于长整数转换为短整数,舍弃高位数,保留低位数。
- 对于短整数转换为长整数,拓展相应的符号位,如果是有符号数,由于采用补码方式进行存储,因此在符号位和数值位之间加上 1 ,如果是无符号数,直接在数值位之前加上 0 。
数据的存储和排列
- 大小端模式
- 对于一个连续的多字节数据,例如如图所示的十六进制数据,由于是两位数占据一个字节的存储空间,因此我们将左侧的最高位 01 命名为最高有效字节(MSB),同时将右侧的最低位 67 命名为最低有效字节(LSB)。
- 由于一个连续的数据具有大小端,因此我们在程序中的存储也有了两种方式,分别为大端存储和小端存储,对于大端存储更符合人类从左向右读的阅读习惯,对于小端存储更便于计算机在进行计算时先处理低位字节。
- 边界对齐
- 现代计算机通常使用按字节编码的方式,即按照每个字节对应 1 个地址。
- 通常也支持按照字,按半字,按字节寻址。
- 假设存储字长为32位,则 1 个字 = 32 bit ,半字 = 16 bit。每次访存仅读写一个字。
下图为按照字节存储的方式
下图为按照半字存储的方式
下图为按照字存储的方式
- 当进行转换时,如果是将按字存储转换为按字节存储,那么就将地址向左移动两位,例如将01 -> 0100。
下图为边界不对齐方式
如果需要存储一个有 3 个 char 类型,3 个 short 类型,1 个 int 类型的结构体时。
- 通过上图的存储,我们可以看到由于一次仅可以读写一个字,当在边界不对齐时读取一个 int 时我们需要读写两次,当在边界对齐时我们仅仅需要读取一次。
- 对于边界对齐的方式属于是用空间换时间,对于边界不对齐的方式属于是用时间换空间。
浮点数表示
- 从科学计数法理解浮点数
在进行十进制的运算时,为了方便数据的表示,我们使用了科学计数法进行表示一些很大的数据。由于底数 10 是固定的,因此我们可以省略 10 。
我们可以采用这样的存储方式,使用阶码和尾数分别表示数值的大小和数值的精度。
- 浮点数的表示
- 阶码:常常使用补码或移码表示的定点整数,反映了浮点数的表示范围和小数点的实际位置。
- 尾数:常常使用原码或补码表示的定点小数,反映了浮点数的精度。
- 规格化
为了保证尾数的最高数值位是一个有效值,我们可以采用左规和右规的方式。
- 左规:当浮点数尾数出现类似于0.01的情况时,我们可以采用左规的方式使其成为0.10 ,使其尾数算数左移一位,阶码减一。
- 右规:当浮点数运算的结果出现尾数溢出(例如:双符号位为 01 或 10),将尾数算数右移一位,阶码加一。
- 当使用原码表示的尾数进行规格化时
- 正数为 0.1…… 的形式,表示的最大值为 0.11……1;最小值为 0.10……0
- 负数为 1.1…… 的形式,表示的最大值为 1.10……0;最小值为 1.11……1
- 当使用补码表示的尾数进行规格化时
- 正数为 0.1…… 的形式,表示的最大值为 0.11……1;最小值为 0.10……0
- 负数为 1.0…… 的形式,表示的最大值为 1.01……0;最小值为 1.00……0
负数的最高数值为 0 是由于为了符号位和最高数值位不同,便于计算机硬件判断是否已经完成了规格化。
- 采用原码表示,规格化尾数最高数值位一定为 1
- 采用补码表示,规格化尾数最高数值位一定为和符号位相反
虽然使用浮点数表示的相同位数的数值大小远远大于定点数,但是仍会存在一个范围
- 当表示的浮点数范围大于了最大正数或最小负数,我们称之为正上溢或负上溢。通常当作机器 0 处理。
- 当表示的浮点数范围小于了最小正数或最大负数,我们称之为正下溢或负下溢。通常当作异常处理。
IEEE 754
- 移码
在补码的基础上对符号位进行取反,注意,移码仅仅可以表示整数。
定义:移码 = 真值 + 偏置值
例如,一个 8 位移码的偏置值 = 128D = 1000 0000B ,即2n-1。
在IEEE 754的规定中,移码的偏置值为 2n-1-1。
在进行运算中,当真值为负数时,偏置值(被减数)可能出现小于真值(减数)的情况,但是由于我们的运算都是模 28的运算,因此我们可以先为被减数加上28,再进行运算。
- IEEE 754标准
- 对于标准的浮点数来讲,由三部分组成,分别是数符,阶码(使用移码表示),尾数(使用原码表示)。
- 数符表示一个浮点数类型的正负性。阶码由于-128,-127代表的全 1 和全 0,有特殊的作用。因此,真值的表示范围是 -126 ~ 127 之间。尾数由于前面有一个默认的 1 ,因此仅仅表示 23 位即可。
- 注意:最高位为符号位,尾数中没有符号位。
- 对于一个如图所示的浮点数类型,由于阶码的真值 = 移码 - 偏置值。因此一个规格化的短浮点数类型的真值为(-1)s * 1.M * 2E-127
最小绝对值:尾数全为 0 ,阶码的真值最小为 -126,对应的机器数 0000 0001,此时整体的真值为 1.0 * 2-126
最大绝对值:尾数全为 1 ,阶码的真值最小为 127,对应的机器数 1111 1110,此时整体的真值为 1.0 * 2127
特殊情况:
- 当阶码全为 0,尾数 M 不全为 0,表示非规格化小数 正负(0.xx…x)2*2-126
- 当阶码全为 0,尾数 M 全为 0,表示真值 正负 0
- 当阶码全为 1,尾数 M 全为 0,表示真值 正负无穷大
- 当阶码全为 1,尾数不全为 0 ,表示非数值“NAN”
浮点数加减运算
- 先求出每个数的补码表示形式
先求出原码格式,再转换为补码格式。
- 运算步骤
- 对阶
使两个数的阶码对其,小阶向大阶看齐,尾数每右移一位,阶码加 1
根据判断阶差得到两数之间的差值,接着小阶向大阶看齐。
- 尾数相减
- 规格化
- 舍入
无需舍入
- 判溢出
常阶码,无溢出
- 舍入方法
- “0”舍“1”入法:类似于十进制中的四舍五入,在尾数进行右移时,被移除的最高位数值位为 0 ,则舍去,被舍弃的最高数值位为 1,则在末位加 1,但是由于这样做会使得尾数溢出,一次可能还会需要一次右规。
- 恒置“1”法:尾数进行右移时,我们丢弃的数值是“1”还是“0”,都将右移后的尾数末位恒为“1”。但是该方法同样会导致尾数变大和变小的两种可能。
- 强制类型转换
- 如今的计算机大多数都是 64 位,但是由于计算机组成的书籍出版时间较早,因此大多数考题使用 32 位的计算机作为样本。
- 在 32 位 和 64 位中需要特别注意 long 型变量,当在进行 long 转换为 double 类型时,如果是在 32 位机器中不会有精度损失,但是在 64 位机器中,由于 double 类型的双精度浮点数的尾数的范围是52位,加上隐藏的 1 位,总共是 53 位,因此当 64 位的数据转换到 53 位中,会造成精度损失。
- 当进行 int(-231 ~ 231-1) -> float( 2-126 ~2127*[1,2) ) 时,由于int 有效数值是 32 位,float 有效数值为 24 位,因此会造成精度的损失。当 float -> int 时,可能会造成数值溢出和精度损失(当 float类型表示一个很小的数值时)。