背景
在IEEE标准754之前,业界并没有一个统一的浮点数标准,相反,很多计算机制造商都设计自己的浮点数规则,以及运算细节。那时,实现的速度和简易性比数字的精确性更受重视。
直到1985年Intel打算为其的8086微处理器引进一种浮点数协处理器的时候,聪明地意识到,作为设计芯片者的电子工程师和固体物理学家们,也许并不能通过数值分析来选择最合理的浮点数二进制格式。于是Intel在请加州大学伯克利分校的 William Kahan教授──最优秀的数值分析家之一来为8087 FPU设计浮点数格式; 而这个家伙又找来两个专家来协助他,于是就有了KCS组合(Kahn, Coonan, and Stone)。 他们共同完成了Intel的浮点数格式设计,而且完成地如此出色,以致于IEEE组织决定采用一个非常接近KCS的方案作为IEEE的标准浮点格式。目前,几乎所有计算机都支持该标准,大大改善了科学应用程序的可移植性。
浮点数表示
S(符号位) | E(指数位) | M(有效数字位) |
---|---|---|
31 (共1位) | 30 – 23 (共8位) | 22 – 0 (共23位) |
浮点数n的公式如下
$$
n=(-1)^s \times m \times 2^e
$$
- S(sign)表示N的符号位。对应值s满足:
n>0
时,s=0
;n<0
时,s=1
。 - E(exponent)表示N的指数位,位于S和M之间的若干位。对应值e值也可正可负。
- M(mantissa)表示N的尾数位,恰好,它位于N末尾。M也叫有效数字位(sinificand)、系数位(coefficient), 甚至被称作“小数”。
计算方式
下面是C语言的计算方式
#include <stdio.h>
#include <math.h>
typedef unsigned long u32;
// 十六进制数转浮点数通用方法
float HexToFloat(unsigned long number)
{
// 计算符号
u32 sign = (number & 0x80000000) ? -1 : 1;
// 计算指数
u32 exponent = ((number >> 23) & 0xff) - 127;
// 计算有效数字
float mantissa = 1 + ((float)(number & 0x7fffff) / 0x7fffff);
// 组合计算结果
return sign * mantissa * pow(2, exponent);
}
// 测试用例
int main()
{
unsigned long a = 0x40490FD0;
float result = HexToFloat(a);
printf("结果 = %f \n",result);
return 0;
}