前言
浮点类型的取值范围与精度是自我学习变成编程以来一直疑惑的点,趁这次面试刷题的机会,自我解惑。文章内容多方整合,有摘录他人,有自我理解,若有疏漏错误,望见谅,也欢迎留言斧正。
一,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字节,为什么