3.4.2 舍入误差
考虑到浮点数的表示形式,任何使用浮点数的运算都有可能存在舍入误差。因为最初设计浮点数的时候,我们使用了一个有限的数来近似地表示一个实数,而这个实数的范围可以大到无限大。表3-2展示了浮点数的表示方式(以3.88f为例)。
表3-2:浮点数表示
3.88f后面接下来三个连续的32位浮点表示是:
随机选择三个32位的单精度浮点数,表示为:
在32位浮点数中,1位用于表示符号,8位用于表示指数,23位用于表示尾数(也就是有效数)。在Java 的浮点表示中,“将指数部分作为一个正数,然后从这个正数中减去一个基准值,得到2的幂。对于一个浮点数来说,这个基准值是126”(Venners,1996)。如果指数部分是128,那么实际的指数值是128-126,即为2。
为了得到最高的精确度,尾数必须是标准化的,因此最左边的数字永远是1。虽然并不需要每次都物理上存储这一位,但是浮点数处理器必须要遵守这条标准:那就是左边永远应该是1,并且在需要的时候补上这一位。在之前的例子中,尾数是.[1]11110000101000111101100 = [1/2] + 1/4 + 1/8 + 1/16 + 1/32 + 1/1024 + 1/4096 + 1/65 536 + 1/131 072 + 1/262 144 + 1/524 288 + 1/2 097 152 + 1/4 194 304 ,四舍五入之后,这个和是0.9700000286102294921875。
因此,当使用这种表示方法存储3.88f时,近似值是 + 10.9700000286102294921875*22,也就是3.88000011444091796875。固有误差为~0.0000001。描述浮点误差最常用的方法是使用相对误差——相对误差计算的是绝对误差和期望值的一个比率。在这里,相对误差是0.0000001144091796875/3.88,或者写作2.9E-8。低于10-6的相对误差是相当普遍的。