C、C++中使用到的单精度浮点数(float)类型和双精度浮点数(double)类型是在IEEE二进制浮点数算术标准(ANSI/IEEE Std 754-1985)中定义的。下面分别从存储格式、内存分布、编码规则、取值范围、有效数字位数和测试示例程序六个部分来详细说明。
存储格式
浮点数在计算机中存储时,按照二进制科学计数法拆分为三个部分:符号位、指数部分和尾数部分。如下图所示:
单精度和双精度浮点数数据类型详解
存储时,按照最高位存储符号位,次高位存储指数部分,低位存储尾数部分的次序存储。存储时的排列示意图如下:
单精度和双精度浮点数数据类型详解
内存分布
float类型和double类型的各部分在内存中的存储空间占用如下表:
单精度和双精度浮点数数据类型详解
float类型的内存分布如下图所示:
单精度和双精度浮点数数据类型详解
double类型的内存分布如下图所示:
单精度和双精度浮点数数据类型详解
编码规则
在实际存储时要对使用二进制科学计数法表示的浮点数值的符号位、指数部分和尾数部分进行编码处理。一般需要分为规约形式的浮点数、非规约形式的浮点数和特殊值三种类型进行编码。其编码前后处理如下图所示:
单精度和双精度浮点数数据类型详解
注:非规约浮点数主要用于扩大0值附近的浮点数表示范围,非规约浮点数的绝对值均小于规约浮点数的绝对值,即前者在实数轴上更靠近0,这样可以提高0附近的计算精度;一般C、C++中float和double的取值范围都是按照规约浮点数定义的,MSDN文档和相关教材也是这么说的,但部分编译器按照ANSI/IEEE Std 754-1985标准实现了非规约浮点数,本文末尾留有程序示例说明。
符号位:0表示正数,1表示负数;
指数部分: float的偏移量为2^8 - 1,double的偏移量为2^11 - 1;
尾数部分:实际尾数部分中的小数点后的数值,规约浮点数使用标准的二进制科学计数法表示,其尾数范围在 [1,2),非规约浮点数的尾数部分范围在(0,1)。
下面以规约浮点数8.5为例,来说明浮点数的编码过程:
单精度和双精度浮点数数据类型详解
取值范围
单精度浮点数的各种极限值和取值范围如下图所示:单精度和双精度浮点数数据类型详解
双精度浮点数的各种极限值和取值范围如下图所示: 单精度和双精度浮点数数据类型详解
有效数字位数
因为有效数字位数只与位数有关,所以只要计算出十进制表示的尾数中有效数字位数就能知道该浮点数的有效数字位数。
单精度和双精度浮点数数据类型详解
注:在接近0、正无穷、负无穷等极限值时,有效数字不能保证为上述精度。
测试示例程序
浮点数据表示测试可以通过IEEE-754 Analysis网页在线测试,也可以通过自己编写的C\C++程序来测试。
一下是在Visual Studio 2010下编写的C++测试代码:
单精度和双精度浮点数数据类型详解
输出结果如下:
单精度和双精度浮点数数据类型详解
从上述结果可以看出编译器已经实现了ANSI/IEEE Std 754-1985标准中定义的float型和double型浮点数,而头文件定义中并未更新或修改,MSDN文档亦是如此。如下图: |
|