一文掌握计算机必备基础之数据表示及运算(下)

285 阅读7分钟

前言:一文掌握计算机必备基础之数据表示及运算(下)

3 二进制数据的运算

3.1 定点数与浮点数

原码、反码和补码可以表示正负整数和纯小数,对于整数和小数部分兼有的数值却没有办法表示。为了合理表示,我们引入定点数和浮点数的概念

  • 3.1.1 定点数的表示方法
    • 小数点固定在某个位置的数被称为定点数
    • 定点数的表示方法

对于既有整数又有小数的原始数据,需要设定一个合适的比例因子,数据按比例因子缩小成定点小数或扩大成定点整数再参加运算,结果输出时再按比例折算成实际值。

举例: 计算 11.01 + 10.01

  • 选择比例因子 0.01,可将两操作数变换成 0.1101 + 0.1001,但 0.1101 + 0.1001 = 1.0110,运算结果不是纯小数,出现了机器数不能表示的数,即出现了正溢出。

  • 如果选择比例因子 =0.001,可将两操作数变换为 0.01101+0.01001 则运算结果 0.01101+0.01001=0.10110 为正常结果。将 0.10110 除以比例因子 ,可得到正确结果 101.10。

  • 3.1.2 浮点数的表示方法

    引进浮点数的原因如下

    • 计算机处理的很大程度上不是纯小数或纯整数
    • 数据范围大,定点数难以表达

  1. 浮点数的表示格式

先复习一下读书时代学过的科学计数法:





浮点数的表示方法与科学计数法类似,如下:

需要注意的是浮点数规定尾数必须使用小数,如

上面两个浮点数表现形式在计算机中是这样存储的(规定尾数数值位为8位)

  1. 浮点数的表示范围 假设阶码数值取m位,尾数取 n 位(尾数只能为小数):

    • 阶码能够表示的最大值:
    • 算上负数,可得阶码表示范围:
    • 尾数能够表示的最大值:
    • 尾数能够表示的最小值:
    • 尾数能够表示范围有:

结合阶码和尾数即可得浮点数的表示范围,不在此范围内的则溢出,分上溢和下溢,(上溢因为数值太大,下溢因为数值太小)

浮点数的精度

  • 单精度浮点数:使用4字节、32位来表达浮点数(float)
  • 双精度浮点数:使用8字节、64位来表达浮点数(double)
  1. 浮点数的规格化
  • 尾数规定使用纯小数
  • 尾数最高位(小数点后一位)必须是 1

举个例子

+ 11.0101 = 0.110101*2^10
- 11.0101 = 0.0110101*2^11  //尾数最高位为0,不符合
- 11.0101 = 0.00110101*2^100  //尾数最高位为0,不符合
- 11.0101 = 1.10101*2^1  //尾数不是纯小数,不符合

来做两道题检测一下学习效果

  • 例子1:设浮点数字长为16位,阶码为5位,尾数为11位,将十进制数13/128表示为二进制浮点数。
    • 原码 = 反码 = 补码: x = 0.0001101000
    • 浮点数规格化:
  • 例子2:设浮点数字长为16位,阶码为5位,尾数为11位,将十进制数-54表示二进制浮点数
    • 原码:x = 1,110110
    • 浮点数规格化:
  • 3.1.3 定点数和浮点数的对比
    • 当定点数与浮点数位数相同时,浮点数表示的范围更大
    • 当浮点数尾数为规格化数时,浮点数的精度更高
    • 浮点数运算包含阶码和尾数,浮点数的运算更为复杂
    • 浮点数在数的表示范围、精度、溢出处理、编程等方面均优于定点数
    • 浮点数在运算规则、运算速度、硬件成本方面不如定点数

3.2 定点数的加减法运算

  • 整数加法: A[补]+B[补] = [A+B][补](
  • 小数加法: A[补]+B[补] = [A+B][补](

运算的时候,数值位与符号位一同运算,并将符号位产生的进位自然丢掉

  • 🌰 例子1:A = -110010, B = 001101,求 A+B
  • 🌰 例子2:A=-0.1010010,B=0.0110100,求A+B
  • 🌰 例子3:A = -10010000,B = -01010000,求 A+B
  • 🌰 例子4:A= -10010000,B= -11010000,求 A+B

在 🌰 例子4中,我们发现一个很奇怪的问题,A和B都是负数,它们相加结果却为正数,这是为什么呢?
因为A和B都是用8位数字来表示,但是A+B的结果用8位存不下来,于是发生了溢出。
如何判断溢出?

  • 双符号位判断法
    • 单符号位表示变成双符号位:0=>00,1=>11
    • 双符号位产生的进位丢弃
    • 结果的双符号位不同则表示溢出

用这种方法再来看下 🌰 例子4:A = -10010000, B = -11010000,求 A + B

再用这个方法看下 🌰 例子3:A = -10010000, B = -01010000,求 A + B


前面提到的这么多都是关于整数和小数的加法运算,现在来讲整数和小数的减法运算

  • 整数减法: A[补] - B[补] = A + (-B)[补](

  • 小数减法: A[补] - B[补] = A + (-B)[补](mod2)

  • - B[补] 等于 B[补] 连同符号位按位取反,末位加一

    • 如B[补]=1,0010101, - B[补]=0,1101011
    • 例子5:A=11001000,B=-00110100, 求 A-B
      1. A[补] = A[原] = 0,11001000
      2. B[补] = 1,11001100,(-B)[补] = 0,00110100
      3. A[补] - B[补] = A+(-B)[补]=0,11111100
      4. A - B = 111111100

3.3 浮点数的加减法运算

浮点数的加减法运算较之前要麻烦一些,主要有以下步骤

  1. 对阶
  2. 尾数求和
  3. 尾数规格化
  4. 舍入
  5. 溢出判断

  • 对阶

    • 浮点数尾数运算简单
    • 浮点数位数实际小数位与阶码有关
    • 阶码按小阶看齐大阶的原则

    对阶的目的是使得两个浮点数阶码一致,使得尾数可以进行运算

接下来看个例子:,它们如果要进行加减运算,首先要进行下面对阶操作


  • 尾数求和

    • 使用补码进行运算
    • 减法运算转化为加法运算: A - B = A + ( - B)


    x[原] = 00.0011, x[补]=00.0011
    y[原] = 11.1010, y[补]=11.0110

尾数求和完成以后,接下来要进行尾数规格化

  • 尾数规格化
    • 对补码进行规格化需要判断两种情况:S>0 和 S<0

前面尾数求和得到 S = (x+y)[补] = 11.1001
利用上述的公式进行规格化处理后, S = (x+y)[补] = 11.0010

通过补码求得其原码为 (x+y)[原] = -0.1110,带上阶码最终结果为:

  • 尾数规格化(右移)

    • 一般情况下是左移
    • 双符号不一致下需要右移(定点运算的溢出情况)
    • 右移的话需要进行舍入操作
  • 舍入

    • “0舍1入”法(二进制的四舍五入)

假设 S[补] = 10.10110111,可知符号位为 10,符号位不一致则需要进行右移的操作,右移之后可得 S[补] = 11.010110111

最后一位的1没有办法存储,需要进行舍入操作(0舍1入)

浮点数运算同样需要考虑溢出的情况,现在来讲解溢出判断

  • 溢出判断

    • 定点运算双符号位不一致为溢出
    • 浮点运算尾数双符号位不一致不算溢出,因为尾数双符号位可以进行右移
    • 浮点运算主要通过阶码的双符号位判断是否溢出
  • 例子:,假设阶码4位,尾数8位,计算x+y

在进行规格化的时候,移位了记得阶码也要相应改变

最后来张脑图总结一下浮点数加减法运算的全流程

3.4 浮点数的乘除法运算

下图是浮点数乘除法运算的各个流程

  • 乘法:阶码相加,尾数求积
  • 除法:阶码相减,尾数求商
  • 🌰 例子:,假设阶码4位,尾数8位,计算 x*y

小结

知识点基本都是公式,繁多易忘,温故而知新。看完还想找题目再练练的朋友可以私信我,我这里有几十道附带答案的相关计算题可供练习。

感谢阅读

本文使用 mdnice 排版