float的范围和精度(为什么float的容量比long高?)

float的范围和精度(为什么float的容量比long高?)

在[Java基本数据类型详解(为什么byte的范围是-2^7 ~ 2^7-1?)]((7条消息) Java基本数据类型详解(为什么byte的范围是-2^7 ~ 2^7-1?)_武正康的博客-CSDN博客)中我们聊到,float占据四个字节,而long占据八个字节,可是当float类型的数据转换成为long类型时仍然需要强制类型转换,这是为什么呢?今天我们就聊一聊float范围和精度。

float的存储方式

我们知道科学计数法是(±)a.b*10c,其中a的范围是1到9,b是小数点之后的所有数字,c是10的指数。而计算机中存储的是二进制数字,所以float的存储的数字要转换成(±)a.b*2c,由于二进制中最大的数字就是1,所以可以写成(±)1.b*2^c,因此计算机只需要储存(±),b和c就可以了。

float占用四个字节32位划分为:

  1. Sign(1位):用来表示浮点数是正数还是负数,0表示正数,1表示负数。
  2. Exponent(8位):指数部分。即上文提到数字c,但是这里不是直接存储c,为了同时表示正负指数以及他们的大小顺序,这里实际存储的是c+127。
  3. Mantissa(23位):尾数部分。也就是上文中提到的数字b。

float的存储示例

以数字8.125为例,看一下这个数字是怎么存储在float变量中的:

  1. 整数部分转换为二进制是1000。
  2. 小数部分转换为二进制是0.001。
  3. 拼接在一起是1000.001,类似于科学计数法的样式得到1.000001*2^3。
  4. 从上面的结果中我们可以得到符号为正,b为000001,c为3,这里指数部分实际存储的是130。

具体的表示为:

SEEEEEEEEMMMMMMMMMMMMMMMMMMMMMMM
01000001000000100000000000000000

note(小数部分如何转换为二进制)

小数部分乘以2,得到的结果取整数部分依次从左往右放到二进制数小数点后,直至结果的小数点后为0。例如十进制的0.125,要转换为二进制的小数

步骤数结果整数部分
10.125*2=0.250
20.25*2=0.50
30.5*2=11

所以十进制的0.125转换为二进制位0.001。

float的范围

明白了了float的存储原理之后便能计算float的范围,找到所能表示的最大的数,变换以下符号之后便是所能表示的最小的数。

那么可以得到尾数0.1111111 11111111 11111111,指数为1111 1111,但是指数全是1时有特殊用途,所以指最大时1111 1110,指数减去127得到127,所以最大的数字就是1.1111111 11111111 11111111 * 2^127,这个值为340282346638528859811704183484516925440,通常表示为3.4028235E38,那么float的范围就出来了:[-3.4028235E38, 3.4028235E38]。

float的精度

先看整数部分

指数位有8位,范围是[0,255],指数为全部为1有其他的用途,所以范围是[0,254],根据指数的存储规则,实际上指数的范围是[-127,127]。

尾数位一共有23位,范围是[0,223-1],而公式的表示发为1.b*2c,因此尾数位前面还有一个1,因此实际范围是[0,224-1],换算成十进制就是16777215,所以整数[0,16777215]都能精确的表示,因为他们都能写成1.b*2^c的形式,只要配合调整指数c就可以了。

那不超过最大范围的整数能否精确表示呢?

更大的数字如16777216,因为正好是2 的整数次幂,所以这个数字是可以精确表示的。

再大一点呢?

实际上只要在float的范围内,能够写成1.0000000 00000000 00000000*224*2n + 0.xxxxxxx xxxxxxxx xxxxxxxx*224*2^n的整数都能够精确表示。

解释下这个公式,对于16777216之前的整数都是能够连续精确表示的,但是在其之后便开始出现跳跃,随着n的逐渐增加,跳跃间隔也逐渐变大。

例如当n=1时,每次跳跃间隔为225,当n=2时,每次跳跃间隔为2^26。

再看小数部分

并不是所有的小数都能够精确的表示,小数部分的表示和整数部分密切相关。

例如1.0000000 00000000 00000000*27,这里23位尾数位中有7位是用来表示整数部分的,剩下的16位才是用来表示小数部分的。

假设有m位是用来表示小数部分的,那么小数部分的二进制表示为0.xxxxxxxx(一共有m个x),在这个前提下能够用哦0.xxxxxxx(一共有m个x)所能表示的小数便是精确的小数。

顺便说明以下,当指数为超过23时,便无法在表示小数部分。

float的特殊值

符号位指数位尾数位数值含义
0全为0全为0+0正数0
1全为0全为0-0负数0
0全为0任意取值f0.f*2126非标准值,尾数前改为0,提高了精度
1全为0任意取值f-0.f*2126非标准值,尾数前改为0,提高了精度
0全为1全为0+infinity正无穷大
1全为1全为0-infinity负无穷达
0/1全为1不全为0NaN非数字,用来表示一些特殊情况
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值