C/C++浮点数简述一:模型
c/c++采用IEEE表示法存储浮点类型,公式为:
(-1)s x M x 2 E
其中:
s是符号位,决定正数(0)还是负数(-1),数值为0的数字符号位做特殊处理。
M是二进制有效数。
E是2的幂,作用是对2进制加权。
那么在C中,存储格式如下:
|
s
|
f(M=1+f orM=f)
|
e(E=e-bias ,bias 为 2k-1 , k为 E 的位数)
|
0(1位) | 1-23(23 位) | 24-31(8位 ) | 32位
0(1位) | 1-52(52 位) | 53-63(11位 ) |64 位
而根据 E的值的不同浮点数的表示方法有一下三种:
规范化值:
E为无符号数,当E不是全 0或者全1 时,此时就是用于规范化表示。
E = e-bias,e 为k位, k为E 的位数, bias为2 k-1 ,由此确定,E的取值范围
对于单精度来说是 -126 - +127,双精度为-1022 - + 1023 。
M=f+1(0<=f<1 ),即二进制值为 0.fn-1 fn-2…f 1f0 ,需要注意的是 隐含的1 ,因为我们总是能够调节指数,使 1<=M<2,那么小数第一位肯定是 1,而这个1 我们就不用显示的表示它了,这样可以获得额外一位。
非规范化值:
当指数E 二进制位全 0时,所表现的数就是非规范化形式的,这种情况下指数值为 E=1-bias,
而M=f,此时 1不被隐含。因为规格化时有一个隐含的 1,所以不能表示0,而规范化值可以表示 0。+0和负0在IEEE标准中是是不一样的,但是C库是不区分的,但有个例外:1/负0结果是负无穷,而1/正0结果是正无穷。正0和负0比较是一样的。我觉得C库应该是在0参与的运算当中是区分正负的,但是直接比较0时,是不区分的。这里使用1-bias 是为了从非规范化值向规范化值的平滑转换,非规范化值的最大表示恰巧是规范化值的最小表示,此时转换,我们只需要将 e转为1 ,再加上一个隐含 1就可以完成。
特殊值:
当指数值 E为全1 ,M全为 0时,表示的值是无穷,当 s为0 时,表示的是正无穷,当 s为1 时,表示的是负无穷,当小数值不为 0时,结果为NaN ,即不是一个数,如求 -1的开根。
具体的IEEE标准可以参看wiki http://zh.wikipedia.org/wiki/IEEE_754

浙公网安备 33010602011771号