前言
   
浮点类型的取值范围与精度是自我学习变成编程以来一直疑惑的点,趁这次面试刷题的机会,自我解惑。文章内容多方整合,有摘录他人,有自我理解,若有疏漏错误,望见谅,也欢迎留言斧正。
    
    
    一,Java中的浮点型
   
| – – – | float | double | 
|---|---|---|
| 类型 | 单精度 | 双精度 | 
| 字节 | 4 | 8 | 
| 比特 | 64 | 32 | 
    
    
    二,浮点型的储存方式
   
    
     与整型不同,浮点型以科学计数法保存数据。
    
   
    在十进制中,科学计数法会将数字转化为(±)a.b x 10
    
     c
    
    的形式。其中a表示整数(范围1~9), b表示所有小数,而c表示指数。同理,二进制中也有同样的表示形势(±)a.b x 2
    
     c
    
    ,英文字符的含义相同。因为二进制中最大值为1,所以a的数值也就固定为1,无需保存,因此也可以写成(±)1.b x 2
    
     c
    
    。故而可知浮点型只需要保存(±),b,c三个值,便可以把整个数字保存下来。
   
    
    
    三,浮点型的内存分配
   
无论是float还是double,其储存方式(思想)都是相同的,区别只在于储存空间大小不同。
    
     浮点型内存空间分为四个部分:
    
   
- 
     
 
 符号位(Sign):用于保存浮点数的正负号(0:正,1:负);
 
- 
     
 
 指数符号位(Exponent Sign):用于保存指数位的正负号;
 
- 
     
 
 指数位(Exponent):影响浮点数的取值范围;
 
- 
     
 
 尾数位(Mantissa):影响浮点数的精度。
 
浮点型的具体内存分配如下:
| – – – | 符号位 | 指数符号位 | 指数位 | 尾数位 | 总计 | 
|---|---|---|---|---|---|
| float | 1 | 1 | 7 | 23 | 32 | 
| double | 1 | 1 | 10 | 52 | 64 | 
很容易看出,内存的划分与存储方式是相互对应的,其中指数(b)包含指数符号位和指数位两个部分。
    
     示例
    
   
此处以float类6.5为例,讲解浮点型的储存方式。
    (1)将6.5整数部分6转化为二进制形式,得110;
    
    (2)将6.5整数部分0.5转化为二进制形式,得0.1(求小数二进制的方法自查);
    
    (3)整合上述步骤,得6.5的二进制形式为110.1;
    
    (4)将110.1转化为科学计数法形式,得1.101 x 2
    
     2
    
    ,得符号位0,指数符号位0,指数位2,转化二进制形式为10,尾数位101;
    
    (5)将以上的数据保存在各自的内存中,如下表所示
   
| S | ES | E | E | E | E | E | E | E | M | M | M | M | M | M | M | M | M | M | M | M | M | M | M | M | M | M | M | M | M | M | M | 
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 
(6)于是0 0 000001 000000000000000000000101表示的就是6.5在内存中的具体储存。
    
    
    四,浮点型的取值范围
   
    
     
      注:下文中的1.1…表示1.11111111111111111111111(小数23位)。
     
    
   
在其它文章中,一般都会说浮点型的取值范围受指数影响,但实际上尾数对之也有影响,具体的情况再下一节具体描述,此处还是先通过指数求取值范围。
依然以float为例。float类型与指数相关的内存一共8bit,指数符号位1bit,指数位7bit。很容易就能得出,指数的取值范围:
    
     [-127,128]
    
   
    以此为基准,我们求float的最大值。这里我们加个前提,
    
     符号位始终为正(注意是符号位,不是指数符号位)
    
    ,很容易就能求得,最大值为1.1… x 2
    
     128
    
    ,这个值为340282346638528859811704183484516925440,通常表示为3.4028235E38,也就是我们常见的float取值范围的最大值。
    
    接下来求最小值,因为符号位始终为正,因此最小值不是-3.4028235E38,而是1.1… x 2
    
     -127
    
    ,这是一个无限接近于0但又不为0的小数。因此我们可以知道,在符号位始终为正的情况下,float的取值范围是:
   
    
     [1.1… x 2
     
      -127
     
     ,1.1… x 2
     
      128
     
     (3.4028235E38)]
    
   
我们在将符号为负的情况也考虑进去,可知,float的真正取值范围是:
    
     [-1.1… x 2
     
      128
     
     (-3.4028235E38),-1.1… x 2
     
      -127
     
     ] ∪ [1.1… x 2
     
      -127
     
     ,1.1… x 2
     
      128
     
     (3.4028235E38)]
    
   
这个结论与实际范围[-3.4028235E38,3.4028235E38]不同,我们暂且放在这里,继续向下看。
    
    
    五,精度限制
   
我一直都有疑惑,float与int同是4字节,为什么
 
