Java浮点运算精度

摘要

  Java语言中支持两类非整数类型,float和double(以及包装类Float和Double)。还有一个特殊的类,任意精度小数BigDecimal。大多数编程情况都很少用到浮点数等的运算,但是在实际应用中,这些非整数运算总是出现错误的计算结果。文章将讨论非整数类型的基本原理,如何使用非整数得到正确的结果,以及BigDecimal的推荐使用。

存储原理

  计算机中以底数为2的小数来表示浮点数。
  在32位的float类型浮点数中,通常用1位表示数字符号,8位表示指数,其余23位表示小数部分。有符号数据指数部分有正负之分,小数部分由以2为底的小数表示。即最高为对应为(2 -1)。下一位对应(2 -2),以此类推。
  对于64位双精度double类型,1位表示数字符号,11位表示指数,其余52位表示小数部分。
 sexponentmantissa
float1823
double11152
  对于数字1.25,float表示值为0 0111 1111 010 0000 0000 0000 0000 0000。其中0表示正数,0111 1111(127)为指数。0.01其值加1的1.01为小数。计算公式为v=(-1)^s*(1*2^1+0*2^0+1* -1)*2^(E-128),所以float类型数据计算公式为 v=(-1)^s*M*2^(E-128)。M表示小数位计算方法,如1.25计算方法。 双精度double计算公式为 v=(-1)^s*M*2^(E-1024),

计算误差

  float数据311.29,其真实值是311.2900085449219浮点数的计算机存储方式注定其不能精确的表示所有数据,因此,float和double型数据在计算过程中的误差是在所难免的。

比较错误

  1,运算过程中,当比较其值是否大于0时,由于误差的存在,会出现错误的比较结果。
  2,对于特殊情况,无穷大NaN,正负零的比较需特别注意。比如0是不等于-0的。

BigDecimal

  BigDecimal是在jdk1.3中增加的内容,属于标准类库,可表示任意精度的小数。其通过任意精度任何范围的值和一个换位因子来表示BigDecimal,换位因子表示小数点左移的位数。用BigDecimal表示的值为unscaledValue*10 -scale 。
  BigDecimal有多个构造函数,其中一个构造函数以双精度浮点数作为输入,另一个以整数和换算因子作为输入,还有一个以小数的 String 表示作为输入。小心使用 BigDecimal(double) 构造函数,double在计算存储中存在误差,有可能导致构造完的BigDecimal就存在误差。请使用基于整数或 String 的构造函数。BigDecimal 提供了基本的加、减、乘、除等算数运算,由于其对象的不可变性,在运算的过程中都会产生新的BigDecimal 对象。创建对象的开销,因此在使用BigDecimal时需谨慎,避免用于大量数学计算。

总结

  1,使用float和double类型在计算时会存在误差,如果需要非常精确的计算,建议使用BigDecimal。
  2,如果数据计算需要进行四色五入到整数,值加0.5的办法处理。
  3,对精度要求不高的环境下,比如测量值,允许存在误差且float和double导致的误差在其范围内。float和double数据原型是比较好的选择。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值