目录
二进制小数
十进制小数转二进制小数
IEEE浮点表示
规格化表示
非规格化表示
特殊值
舍入
浮点运算
二进制小数
类比十进制中的小数,可定义出二进制小数
例如1010.0101
小数点后的权重从-1开始递减。
十进制小数转二进制小数
整数部分使用辗转相除,小数部分按照如下方法
乘2取整,顺序排列。
例如把0.8125转化为二进制小数
......取整得1,小数部分乘2
......取整得1
......取整得0
......取整得1
故二进制小数表示为0.1101
IEEE浮点表示
该标准类似十进制的科学计数法来表示一个小数
s是符号位,对于数值0的符号位解释为特殊情况
M是尾数,或
阶码,E的作用是加权
将浮点数的位表示划分为这三部分,
一个单独的符号位s直接编码s,
k位阶码字段exp表示E
n位编码尾数frac是M
C语言中float阶码为8位,尾数23位;double阶码为11位,尾数52位。
编码分为三种
规格化表示
当阶码的位非全0也非全1时
对于k位阶码表示,,e是k位无符号数,Bias是偏移量,大小为
对于n位小数字段,在规格化表示下,只存储了小数点右边的值,在计算最终值时再加上1,因为左边的值恒为1,这样可多一位精度。
非规格化表示
当阶码的位为全0时
对于k位阶码表示,,在这e = 1,Bias是偏移量,大小为
对于n位小数字段,只存储小数点右边的值,这时不会计算最终值时加1。
关于为什么e取1不取符合直觉的0,是为了在规格化表示的最小数和非规格化表示的最大数之间的平滑过渡。
下文将举例解释。
特殊值
阶码全1时,若n位小数字全0则表示正负无穷,否则表示NaN(Not a Number)。
下面举个例子来理解编码,例如十进制小数3.75,转化为二进制小数为11.11,我们要将它表示为一个float类型的数,也就是说有8位阶码,Bias=127,23位小数字段。
将其转为类似科学计数法的形式
符号位s为0,得,算出e的8位二进制表示为,23位只存储小数点后的23位,为。
现在举例说明非规格化表示e取1的问题,例如float能表示的最大非规格数是阶码全0,小数位全1,表示的二进制小数是
而最小的规格化表示是阶码最低位为1,阶码其余位为0,小数位为全0,则表示的二进制小数是
可以看出这种变化是平滑的,主要原因:对于非规格化表示与规格化表示的阶码取1的情况,它们权重是相等的
舍入
IEEE浮点格式定义了四种舍入法,默认是向偶数舍入,向偶数舍入在非中间值时就是正常的四舍五入,对于有中间值的情况有特殊处理。
这是对十进制小数舍入到整数的例子,对于1.40和1.60比较好理解,对于1.5,采用向偶数舍入,也就是向要保留的最低有效位变成偶数的方向舍入。所以1.5舍入为2,2.5舍入为2,-1.5舍入为-2.
对于二进制的情况来说,难点在于判断是否是中间值。
如0.101011,要保留到小数点后四位,可一眼看出后面的数非中间值。
但对于0.101010,它若要舍入到小数点后四位,有两个方向,0.1010和0.1011,算出0.101010与这两个数的差的绝对值是相同的,说明四位后是中间值,这时采用向偶数舍入的策略,选择0.1010。
浮点运算
对于浮点数相加,例如与相加,会先对齐小数点,将较低的位权的那个数位权提升,于本例就是把变成然后再把小数部分相加。
若相加后小数位数超出了能表示的范围会进行舍入。
可以看到相加中存在移位操作,这种移位操作就很可能造成精度丢失,对于一个大数与小数相加,更有可能造成无法容忍的误差或错误,,,对于第一个算式,3.14在相加时由于舍入会被丢失。
这个例子也能说明浮点加法不满足结合律,改变运算顺序就会改变运算结果。