2.9 浮点数计算与精度损失
前面介绍了浮点数的表示可能丢失精度,其实在浮点数的计算过程中,也可能丢失精度。当对浮点数进行加减乘除运算时,可以采取一种直接的方式。例如对于算式0.5×0.75,0.5的浮点数表示为0|01110110|000 0000 0000 0000 0000 0000,0.75的浮点数表示为0|01110110|100 0000 0000 0000 0000 0000。由于它们的指数位相同,所以可以直接对小数位相乘,相乘后的结果为100 0000 0000 0000 0000 0000。
当前指数位的值为126,对于指数位,采取直接相加的方式126+126=252,接着减去127得到最终的指数值252-127=125。由于符号位全部为0,因此符号位的结果也为0。最终得到的结果为:0|01111101|100 0000 0000 0000 0000 0000。除法运算可以采取相同的操作。
而对于加法和减法运算,需要先调整指数值的大小,再将小数部分直接相加。例如,1.23×1028+1.00×1025需要转换为1.23×1028+0.001×1028,再对小数部分求和,结果为1.231×1028。可以发现,如果浮点数的小数部分只能精确地表示1.23,那么这个加法将被抛弃。在IEEE-754中总是会精确地计算,但是最终转换为浮点数类型时会进行四舍五入操作。在下面说明浮点数精度损失的例子中,1000个0.01相加的最终结果为9.999999999999831。
可以看出,在浮点数的计算过程中可能产生精度的损失,并且精度的损失可能随着计算的次数而累积。同时浮点数的计算顺序也会对最终的结果产生影响。加法运算由于需要进行指数调整,有丢失精度的风险,优秀的开发工程师在执行涉及加、减、乘和除的运算时,会优先执行乘法和除法运算。通常x×(y+z)可以被转换为x×y+x×z,从而得到更高的精度。