二进制小数的定点表示
回忆上面用进制表示数的方法,小数部分的表示与整数部分类似,只不过是多了负的位权。
-
十进制小数 二进制小数:不断乘以2,取整数部分(0或1)依次作为二进制位,直到小数部分为0或达到所需精度。
-
二进制小数 十进制小数:小数点右边第n位的位权是 (n从1开始),将每一位乘以对应的位权()并求和。
例如将13.25转换为二进制:
-
整数部分13转换为二进制:13 ÷ 2 = 6 余 1;6 ÷ 2 = 3 余 0;3 ÷ 2 = 1 余 1;1 ÷ 2 = 0 余 1。倒序排列余数得到1101。
-
小数部分0.25转换为二进制:0.25 × 2 = 0.5 取整为0;0.5 × 2 = 1.0 取整为1。得到二进制小数为0.01。
因此,13.25的二进制表示为1101.01。
二进制小数的无限循环
但是二进制小数只能表示形如 的数,像0.1这样的数在二进制中是无限循环的:
二进制科学计数法:规格化数的表示
规格化数由三部分组成:符号位S,指数E,尾数M
浮点数表示法IEEE 754
-
符号位S:1位,0表示正数,1表示负数
-
尾数M:只存储二进制小数的小数部分,删除
1. -
指数E:表示指数部分,一般用 求得
-
Bias:偏移值,半精度是7,单精度是127,双精度是1023,保证阶码e是非负数
-
e:e=E + Bias,是个无符号整数(exp的十进制表示)
-
阶码exp:e的二进制表示
C语言中常用的浮点数类型有两种:float(单精度)和 double(双精度)。
以float为例:C语言中的float类型占4个字节,也就是32位二进制表示,具体分配如下:
| 字段 | 位数 | 说明 |
|---|---|---|
| (高位:31)符号位S | 1 | 0表示正数,1表示负数 |
| (30~23)阶码exp | 8 | e=E+127 |
| (22~0 低位)尾数M | 23 | 存储二进制小数的小数部分 |
在float类型下,偏移值 。
浮点数数值分类
根据阶码字段将浮点数分为以下几类:
-
规格化数(Normalized Numbers):
- 阶码exp不全为0且不全为1(即 或 )。
- 值的范围:。
-
非规格化数(Denormalized Numbers):
- 阶码exp全为0,尾数M不全为0。
- 用于表示非常接近于零的数值
- 值的范围:。
-
零(Zero):
- 阶码exp全为0,尾数M全为0。
- 有正零和负零两种表示,值为0。
-
无穷大(Infinity):
- 阶码exp全为1,尾数M全为0。
- 用于表示超出表示范围的数值,值为正无穷或负无穷。
-
非数(NaN, Not a Number):
- 阶码exp全为1,尾数M不全为0。
- 用于表示未定义或不可表示的数值(如0除以0)。
舍入误差
这里重点讲偶数舍入(Round to Nearest, Even)
对于十进制数,四舍六入五取偶
例如:在保留小数点后两位的条件下:
- 2.345 约为 2.34 (4是偶数,舍去5)
- 2.355 约为 2.36 (5是奇数,进1)
对于二进制数:
定义最低有效位(LSB)为0的二进制数为偶数,LSB为1的二进制数为奇数。
例如:在保留小数点后两位的条件下:
- 0.1010 约为 0.10 (LSB为0,舍去1)
- 0.1111 约为 1.00 (LSB为1,进1)
舍入误差的影响
浮点数的运算性质
由于舍入误差的存在,浮点数运算(+,*)不满足交换律,结合律与分配率。
类型转换
小类型转大类型():精度不变,数值不变
大类型转小类型():可能发生舍入误差,数值可能改变,或者溢出。