理解浮点数的构成个人觉得对于新手是一个比较困难的事,我就想了好久,看了好几篇参考资料,才大概弄清。。。
下面就说一下自己的理解吧~
关于单精度浮点型的二进制构造:
一般6-8位有效数字(假设float占4个字节,那就是一共32位,其中一个符号位,8个指数位,23个尾数。所以布局如下:
(有效数字大家应该知道吧,回想一下科学计数法)
上面给出了浮点数的表示方法,6-8位有效数字就是10^6到10^8个数(一般超过7位就四舍五入了,后面的就都不精确了),这个与编译器有关。
其实,也就是说每个float类型里面有2^23=83886087个二进制位对应表示2^23个数,10^6<2^23<10^8,所以我们一般可以精确的表示6位有效数字,但是无法表示8位有效数字。浮点数有正负所以需要一个符号位来表示,还有8个指数位来表示指数(指数也是要存储的好吧)由于有正负也就是-127~128。
说道这里,大家感觉可能是懂了,不过很有可能还是没懂。
我给出问题,float能表示的大概的范围-3.4E38~3.4E38,这个数又是怎么来的?
我们知道计算机是以二进制来存取数据的,二进制也有其对应的浮点数形式。比如,1001.101.转换成10进制就是9.625.而对于IEEE标准要求浮点数必须是规范的,小数点左侧必须为1.这样,就变为1.001101*2^3(这里要注意,没错,二进制的科学技术法就是2的n次幂)。所以,对应的32为表示如下。
符号位0|指数幂 10000010|尾数 00110100000000000000000
这里我们看到尾数第一个1省略了(正常应该是100110100000000000000000),因为IEEE规定了小数点第一位是1,所以可以将这个符号位添加到后面来保存更多的数据。
指数位的规则比较复杂,首先,1.001101*2^3,在二进制中不会出现2或者是3的,所以指数为3必须要转换成2进制的形式,3的二进制是00000011。其次,任何实际的指数不能直接存储在指数位里,需要加上一个偏移值127,加完偏移值的这个数叫做阶码,然后这个阶码会存储在表示指数的8位二进制中。这样,3+127 = 130,转换成二进制就是10000010。
那么为什么要加一个偏移值呢?这个偏移值为什么是127?
这个有时间再进一步讨论~
比如,当实际的指数值为0的时候,在2进制的指数位表示为127(实际值=e—127).所以,当实际值为3的时候,e=130(也就是指数位为130,10000010)
最后再举一个例子,
-6.5
符号位1|指数幂 10000001|尾数 10101000000000000000000
现在应该知道那个范围是怎么算出来的吧,
截图就是2^128的结果(浮点数的大致范围由指数位来决定,而尾数决定的是精确程度)。
下面是一个C++中有关基本数据类型的表格:
类型 | 含义 | 最小尺寸 |
bool | 布尔类型 | 未定义 |
char | 字符 | 8位 |
wchar_t | 宽字符 | 16位 |
char16_t | Unicode字符 | 16位 |
char32_t | Unicode字符 | 32位 |
short | 短整型 | 16位 |
int | 整型 | 16位 |
long | 长整形 | 32位 |
long long(C++ 11) | 长整形 | 64位 |
float | 单精度浮点型 | 6-8位有效数字(假设float占4个字节,一个符号位,8个指数位,23个尾数。 2^23=83886087位,2^8<=>(-128~128)\ Float表示-2^128~2^128 内存中 符号位[]+(只存放指数)指数位[][][][][][][][]+尾数[]*23) |
double | 双精度浮点型 | 10位有效数字 |
long double | 扩展精度浮点型 | 10位有效数字 |
大家也可以参考这篇文章,写的很好
http://www.cnblogs.com/findumars/p/5452526.html