Float计算机表示形式

float为什么比int表示的范围广?

什么是单精度和双精度?

float表示小数的时候为什么会有精度丢失?

带着这几个问题,我们来探究下javafloat类型在计算机的表示形式。

javaint占用4个字节,float也是占用4个字节,但是为什么float表示的范围要比int大呢,因为两者在计算机内中表示的方式不一样,int4个字节32位,每一位都是二进制小数表示,最高位0代表是正数,最高位为1代表是负数,所以int的范围是-2^31~2^31-1;

float也是4个字节,遵循IEEE-754格式标准,在计算机中表示有三个部分组成:符号s底数m和指数e

 

符号s最高位,0为正数;1为负数,占用一位;

指数e是该浮点数的指数,二进制表示,最高位为指数符号为1表示大于10表示小于1其实他是用的偏移量表示的,偏移大小为127,没有用补码表示,占用一个字节8

底数m是该浮点数的实际值,二进制形式表示,m的范围是【12】或者【01】占用23位。

所以float在计算机的表示如下面所示:

SEEEEEEEEMMMMMMMMMMMMMMMMMMMMMMM

 

我们先说下10进制和二进制的快速转换方法。

10进制整数2进制转换是除2求商和余数,比如十进制17的二进制计算为:

17 /2=161

16 /2= 8 0

8 /2= 4 0

4 /2= 2 0

2 /2= 1 0

1 /2= 0 1

一直计算到商为0为止,17的二进制表示就是:10001

 

10进制小数2进制表示是乘2求积,比如0.16的二进制计算为:

0.16*2=0.320

0.32*2=0.640

0.64*2=1.281

0.28*2=0.560

0.56*2=1.121

0.12*2=0.240

。。。

所以0.16的二进制表示就是001010….. 一直循环下去,所以除非小数最后为5才能*2取整,否则都会无线循环下去,这就是为什么浮点小数精度丢失的问题。

 

下面我们距离来说明10进制浮点数在计算机的表示, 拿17.16来说:

1.首先为正数,s0

2.二进制为10001.0010100011110101….小数点左移4位为1.00010010100011110101…

3.指数位为4+127=10000011,所以指数位位10000011

4.由于默认最左边为1,所以底数为00010010100011110101…

5.最后17.16的二进制表示就是:01000001100010010100011110101……总共32位,后面的舍弃

 

再拿0.16举例:

1.首先为整数,s0

2.二进制为0.0010100011110101……小数点右移4位为1.0100011110101

3.指数位为4+127=10000011,然后取反为01111100,所以指数位位01111100

4.底数位0100011110101…

5.最后0.16的二进制表示就是:0011111000100011110101…

 

float的(正数)范围:

最小值:Float.MIN_VALUE=1.4E-45 2-149次方:指数位127+底数22
最大值:Float.MAX_VALUE=3.4028235E38 2128次方-1

float是单精度浮点数,4个字节;double是双精度浮点数,8个字节,e占11位,m占52位。

 

注意事项:

1.价格在数据库中保存建议是无符号整形,避免在java转换成浮点数时出现精度丢失的问题;

2.如果需要用浮点型数据进行运算,建议使用BigDecimal,但是BigDecimal的构造函数一定要使用字符串的,否则一样会出现精度丢失的问题:BigDecimal(“123f”)而不是BigDecimal(123f)

3.Float.MIN_VALUE是:1.4E-45,不是一个负数,double也是的。但是整型的MIN_VALUE都是负数

4.floatm只有23位,2^23=8388608,总共有710进制数字,由于最左边的1省略了,所以表示的有效数字最高精确度位78位,包括整数部分,8位后的数字肯定不是准确的

点赞