参考:spa
http://jimmygod.blog.163.com/blog/static/43511339200792605627411/.net
http://blog.csdn.net/archersaber39/article/details/51422602blog
-------------------------------------------------------------------------------ci
我两年前就知道不该该用==号来判断浮点数的相等了,由于存在一个精度的问题,可是一直以来,都没怎么在意这些东西,而实际上,我对于浮点数的结构,虽然了解,但并不清晰. 做为一个C++爱好者,应该尽可能搞清楚每个问题,因此我搞清楚了浮点数的内在表示及实现.在没有大问题的状况下,一切以易于理解和记忆为标准.get
首先说一下原,反,补,移码. 移码其实就等于补码,只是符号相反. 对于正数而言,原,反,补码都同样, 对负数而言,反码除符号位外,在原码的基础上按位取反,补码则在反码的基础之上,在其最低位上加1,要求移码时,仍然是先求补码,再改符号.编译器
浮点数分为float和double,分别占4,8个字节,即32,64位. 我仅以32位的float为例,并附带说double.编译
在IEEE754标准中,规定,float的32位这样分:table
符号位(S)基础 1循环 |
阶码(E) 8 |
尾数(M) 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) 0 |
阶码(E) 00000110 |
尾数(M) 11101101110100101111001 |
注意到,上面的阶码第一位为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位.
--------------------------------------
将20.163转换成754标准的32位浮点数
1.将十进制数转换成二进制数
十进制浮点数,整数部分转换成二进制,采用除2取余法,将余数从低到高排列,即为整数的二进制数;
小数部分转换成二进制,采用乘2取整法,将取整数顺序排列,即为小数的二进制数。
小数部分乘2直到小数部分为0,或取到想要的位数,或循环出现前。
整数部分
20/2=10 .... 0
10/2=5 .... 0
5/2=2 .... 1
2/2=1 .... 0
1/2=0 ..... 1
小数部分
0.163*2=0.326 0
0.326*2=0.652 0
0.652*2=1.304 1
0.304*2=0.608 0
0.608*2=1.216 1
0.216*2=0.432 0
0.432*2=0.864 0
0.864*2=1.728 1
0.728*2=1.456 1
0.456*2=0.912 0
不要求精度时,一般取到8~10位
20.163=10100.0010100110
2.移动小数点到第一、2位之间,得e的值
10100.0010100110=1.01000010100110 *2的4次方 e=4(小数点移动4位)
3.求出S、E、M的值
S=0,E=4+127=131,M=01000010100110
S由小数点的后一位能够看出,0为正数,1为负数。
0 1000001 01000010100110000000000
IEEE754标准中32位浮点数表示
S E M
S是符号位占1位,E是阶码占8位,M是尾数占23位。
当尾数的值不为0时,尾数的最高有效位应为1,这称为浮点数的规格化表示
这样形式的叫规格化
新手初学,有问题或者错误,麻烦评论下 留言指正,谢谢