龙空技术网

为什么Java float和double运算会丢失精度?

不凡的勇者风筝 124

前言:

当前同学们对“java单精度”大约比较重视,小伙伴们都想要了解一些“java单精度”的相关内容。那么小编同时在网摘上网罗了一些关于“java单精度””的相关知识,希望咱们能喜欢,我们快快来学习一下吧!

在java开发中,你也许会遇到浮点数时会丢失精度,那么先看看例子。

double a=3.00;

double b=2.10;

double c=a-b;

System.out.println("c="+c);

c=0.8999999999999999

float e=3.00f;

float f=2.10f;

float g=e-f;

System.out.println("g="+g);

g=0.9000001

显然这结果都不是我们想要的。

为什么浮点型运算为什么会造成精度丢失?

在计算机中,保存这个数使用的是浮点表示法,分为三大部分:

第一部分用来存储符号位(sign),用来区分正负数,这里是0,表示正数

第二部分用来存储指数(exponent),这里的指数是十进制的6

第三部分用来存储小数(fraction),这里的小数部分是001110011

比如float类型是32位,是单精度浮点表示法:

符号位(sign)占用1位,用来表示正负数,

指数位(exponent)占用8位,用来表示指数,

小数位(fraction)占用23位,用来表示小数,不足位数补0。

而double类型是64位,是双精度浮点表示法:

符号位占用1位,指数位占用11位,小数位占用52位。

指数位决定了大小范围,因为指数位能表示的数越大则能表示的数越大。

而小数位决定了计算精度,因为小数位能表示的数越大,则能计算的精度越大。

注意:

程序中应尽量避免浮点数的比较float、double类型的运算往往都不准确

解决方法:

使用BigDecimal提供的方法进行比较或运算,但要注意在构造BigDecimal的时候使用float、double的字符串形式构建,BigDecimal(String val);

运算以减法为例:

BigDecimal a1 = new BigDecimal(Double.toString(a));

BigDecimal b1 = new BigDecimal(Double.toString(b));

double c1 = a1.subtract(b1).doubleValue();

System.out.println("c1="+c1);

c1=0.9

BigDecimal e1 = new BigDecimal(Float.toString(e));

BigDecimal f1 = new BigDecimal(Float.toString(f));

float g1 = e1.subtract(f1).floatValue();

System.out.println("g1="+g1);

g1=0.9

显然0.9才是我们想要的结果。

标签: #java单精度