首先说一下原、反、补、移码。 移码其实就等于补码,只是符号相反。 对于正数而言。原,反,补码都一样, 对负数而言,反码除符号位外,在原码的基础上按位取反,补码则在反码的基础之上,在其最低位上加1,要求移码时,仍然是先求补码,再改符号。
浮点数分为float和double,分别占4、8个字节,即32、位。 在此以32位的float为例,并附带说double。
在IEEE754标准中,规定,float的32位这样分:
| 符号位(S) | 阶码(E) | 尾数(M) |
| 1 | 8 | 23 |
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 |
另外,编译器或电路板一般都有"去噪声"的"修正"能力,它能够使得超过7位的十进制数即使无效了也不会变得离谱,这也是上面为什么一直都是输出333而不是345之类的。 可以这样试一下:
float f=1234567;
cout< 阶码的示数位数是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完全相似,只是它的内在形式是: 有移码表示阶码有是有原因的,主要是移码便于对阶操作,从而比较两个浮点数的大小。 这里要注意的是,阶码不能达到11111111的形式,IEEE规定,当编译器遇到阶码为0XFF时,即调用溢出指令。 总之,阶码化为整数时,范围是:-127~127。 最后,有一个易于出错,一定要记住,浮点数没有无符号型的unsigned float/double是错误的。下载本文
主要的区别在于它的阶码有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位数都是可靠的。符号位(S) 阶码(E) 尾数(M) 1 11 52