视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
浮点数的内存存储格
2025-10-03 00:51:28 责编:小OO
文档
浮点数的内存存储格式

首先说一下原、反、补、移码。 移码其实就等于补码,只是符号相反。 对于正数而言。原,反,补码都一样, 对负数而言,反码除符号位外,在原码的基础上按位取反,补码则在反码的基础之上,在其最低位上加1,要求移码时,仍然是先求补码,再改符号。

浮点数分为float和double,分别占4、8个字节,即32、位。 在此以32位的float为例,并附带说double。

在IEEE754标准中,规定,float的32位这样分:

符号位(S)

阶码(E)

尾数(M)

1823
这里应该注意三点:

A.阶码是用移码表示的,这里会有一个127的偏移量,它的127相当于0,小于127时为负,大于127时为正,比如:10000001表示指数为129-127=2,表示真值为2^2,而01111110则表示2^(-1); 

B.尾数全都是小数点后面的数; 

C.尾数中省略了一个1,因此尾数全为0时,也是1.0…00; 

接下来只要说明几个问题就明白了,以123.456为例,表示为二进制就是:N (2) = 1111011.01110100101111001,这里,会右移6位,得到N (2) = 1.111011 01110100101111001*2^6; 这种形式就可以用于上图中的表示格式了。

符号位(S)

阶码尾数(M)

0(E)  00000110

111011*********01111001
注意到,上面的阶码第一位为0表正,尾数比N(2)表示的第一位少了个1,这就是上面说的默认为第一位为1。 由于在将十进制转为二进制的过程中,常常不能正好转得相等, (当然,像4.0这样的就不会有损失,而1.0/3.0这样的必然损失),所以就产生了浮点数的精度问题,实际上,小数点后的23位二进制数,能影响的十进制数的前8位,这是为什么呢?其实很简单,在上面表示的尾数中,是二进制的,小数点后有23位,最后一位的值为1时,它就是1/2^22=0.000000238实际取的时候肯定是0.0000002,也就是说,对于一个float型的浮点数,其有效的位数是从左到右数7位(包括缺省的1才是7位),当到达上面这个第8位时,就不可靠了,但VC6可以输出最长的1.0/3.0为0.33333333333333331,这主要是编译器的问题了, 而并不是说浮点数小数点后的16位都有效。 如果不信的话,可以去试一下double类型的1.0/3.0, 得到的也将是小数点后17位。                                                                                                  

另外,编译器或电路板一般都有"去噪声"的"修正"能力,它能够使得超过7位的十进制数即使无效了也不会变得离谱,这也是上面为什么一直都是输出333而不是345之类的。 可以这样试一下:

float f=1234567;

cout<这里有一个被人遗忘的问题,就是10进制小数怎么变为2进制小数,其实很简单,就是将10进的小数部分不断乘以2,进位时就将对应的2进制位写入1。 因此将上面的N (2) = 1.111011 01110100101111001*2^6;再转回十进制数时,很可能已经不再是123.456了。 好,精度问题应该说清楚了,下面说示数范围。

阶码的示数位数是8位移码,最大为127最小为-127,这里的127用来作为2的指数,因此为2^127,约等于 1.7014*10^38, 而我们知道,float的示数范围约为-3.4*10^38—3.4*10^38, 这是因为尾数的24位(默认第一位为1)全为时,非常接近2,  1.11…11很明显约为2,因此浮点数的范围就出来了。

double的情况与float完全相似,只是它的内在形式是:

符号位(S)

阶码(E)

尾数(M)

11152
主要的区别在于它的阶码有11位了,这就有2^1023约等于 0.8572*10^308,尾数53位约为2,故double的示数范围约为 -1.7*10^308—1.7*10^308。至于其精度,同样,1.0/2^51=4.4*10^(-16)。小数点后15位有效,加上缺省的那一位,因此对于double浮点数,从左到右的16位数都是可靠的。

有移码表示阶码有是有原因的,主要是移码便于对阶操作,从而比较两个浮点数的大小。 这里要注意的是,阶码不能达到11111111的形式,IEEE规定,当编译器遇到阶码为0XFF时,即调用溢出指令。  总之,阶码化为整数时,范围是:-127~127。

最后,有一个易于出错,一定要记住,浮点数没有无符号型的unsigned float/double是错误的。下载本文

显示全文
专题