定点数,顾名思义,小数点的位置是固定的。整数其实就是定点数的一种,默认小数点在数值部分后面;存储小数时,默认小数点在数值部分前面。也就是说定点数只能表示纯整数和纯小数。因为定点小数不常用,所以这里只介绍一下概念。
浮点数用到了移码,所以我们先介绍一下移码。
补码在比较大小的时候需要额外判断一下符号位,例如:
首先判断符号位,1111 1111
是负数,0000 0001
是正数,所以负数小于正数。但如果直接比较机器码的话:
为了提高比较效率,省略判断符号位的步骤,能不能直接用机器码比较呢?
把所有的数都加一个偏置值,加完偏置值后所有的数都是正数,这样的话就没有正负数的问题了。这种编码方式叫做移码。
移码=真值+偏置值
定点数存在两个问题:1.只能存储纯整数或纯小数。2.表示的数据范围有限。
浮点数可以弥补定点数的不足,顾名思义浮点数的小数点可以浮动,将真值写成科学计数法的形式:
其中为尾数,为阶码,是基数(通常为2)。若要存储N,只需用一个定点小数存储,再用一个定点整数存储即可。
为了提高浮点数的精度,其尾数的最高数位必须是一个有效值,否则需要调整尾数和阶码,这个过程称为规格化。
IEEE 754标准规定浮点数格式如下:
类型 | 数符 | 阶码 | 尾数数值 | 总位数 | 偏置值十六进制 | 偏置值十进制 |
---|---|---|---|---|---|---|
短浮点数 | 1 | 8 | 23 | 32 | 7FH | 127 |
长浮点数 | 1 | 11 | 52 | 64 | 3FFH | 1023 |
临时浮点数 | 1 | 15 | 64 | 80 | 3FFFH | 16383 |
例如将-8.25转换为浮点数,化为二进制为-1000.01,写成科学记数法
阶码用移码表示,所以加上偏移值:
11+01111111=10000010
尾数忽略小数点前面的1:
00001000000000000000000
所以-8.25的二进制为:
数符 | 阶码 | 尾数 |
---|---|---|
1 | 10000010 | 00001000000000000000000 |
浮点数的加减法分为三步:
为了直观,下面的例子并没有遵照IEEE 754 标准,而是阶码用十进制表示,尾数用原码表示,并且没有隐藏位:
对阶按照小阶数化为大阶数的原则。
舍入是因为按照IEEE 754标准,浮点数尾数为23位。而0.000000000000000000000000101(小数点后有27位)不能用23位保存下来,所以舍入成0.00000000000000000000001(小数点后有23位),就是这里的舍入造成的误差。
我们只需知道原理即可,因为在比较先进的芯片中,浮点数的运算已经用电路实现了。在价格较低的芯片中,编译器也会自动生成处理浮点数的代码。