浮点数精度的转换

x86/x64体系里,由于x87 FPU硬件使用扩展双精度格式,因此必然会遇到single/double precision格式与double extended-precision格式之间的互换问题。

转换为扩展双精度数

 

当由单精度数或双精度转换为扩展双精度数时,exponent部分必须基于扩展双精度数的biased码来调整。于是扩展双精度数的exponent值为:

从单精度转化:exponent – 127 + 16383

从双精度转化:exponent – 1023 + 16383

而扩展双精度数的significand部分,由单/双精度数的significand部分移植过来。

单精度数1.11...×2120为例,它转换为扩展双精度的过程如下所示。

浮点数精度的转换

单精度数1.11...×2120的编码值为0x7BFFFFFF,它的exponent值为0xF711110111B),significand部分全为1值。

于是扩展双精度数的exponent值为0xF7-127 + 16383=0x40771000 0000 0111 0111B),单精度23位的significand部分直接移到扩展双精度的bit62bit40位,低40位补0

最终的扩展双精度编码值为0x4077_FFFFFF00_00000000。而对于双精度数来说:52位的significand部分将直接移到扩展双精度的bit62bit11位。

扩展双精度数转换为单精度数

 

而从扩展双精度转换为单/双精度数的情形会复杂得多,涉及目标格式的precison(精度)问题。当扩展双精度significand部分的值超出目标格式的精度时,就会发生rounded(舍入)操作,从而引发precision异常。

要检查超出精度的significand是否为0值,如下所示。

目标格式

超出精度部分

备注

单精度数

bit 39bit 0

是否为0

双精度数

bit 10bit 0

这部分不为0值时,就会发生rounded操作。

下面,我们以扩展双精度数1.11...×2120转化为单精度格式为例进行描述。当1.11...×2120为扩展双精度格式时,它的编码值为0x4077_FFFFFFFF_FFFFFFFF

目标格式exponent部分的计算如下。

单精度数:exponent-16383+127

双精度数:exponent-16383+1023

这个转换过程较为复杂,如下所示。

浮点数精度的转换

图中的阴影部分是超出精度的significand部分(bit 39bit 0),它的值不为0,需要进行rounded操作,在x87 FPU中这个舍入依赖于rounded控制位。

IEEE754定义了以下4种舍入模式。

round to nearest模式:朝±∞(正和负方向的无穷大值)方向舍入。

round down模式:正数朝最大normal值舍入,负数朝-∞方向舍入。

round up模式:正数朝+∞方向舍入,负数朝最大normal值舍入。

round zero模式:正数和负数都朝最大normal值舍入。

上图中的舍入是朝+∞方向舍入,如图所示:bit 39的值为1,它将向bit 40进行舍入,效果等于+1值。目标格式中的significand部分舍入的结果值为0

目标格式的exponent部分为扩展双精度的exponent-16383+127=0xF711110111B,可是由于significand部分还是进位值,因此目标格式的最终exponent部分为0xF8(加上1值)。

因此,最终转换的单精度值为0x7C000000,转换得到的浮点数是1.0...×2121结果大于原来的扩展双精度浮点数。

扩展双精度数转换为双精度数

 

这和转换为单精度数是一致的。在双精度格式里,它的精度是52位,因此超出精度部分为bit10bit0位。

exponent的计算是扩展双精度的exponent-16383+1023

 

 

本文节选自《x86x64体系探索及编程》

电子工业出版社出版

邓志著

你可能感兴趣的:(x86/x64,浮点数精度转换)