摘要

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

存储原理


  计算机中以底数为2的小数来表示浮点数。


(2 -1)。下一位对应(2 -2),以此类推。


  对于64位双精度double类型,1位表示数字符号,11位表示指数,其余52位表示小数部分。




 

s

exponent

mantissa

float

1

8

23

double

1

11

52

  对于数字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*

2  -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,换位因子表示小数点左移的位数。用BigDecimal表示的值为unscaledValue*10 -scale 。

其中一个构造函数以双精度浮点数作为输入,另一个以整数和换算因子作为输入,还有一个以小数的 String 表示作为输入。小心使用 BigDecimal(double)BigDecimal就存在误差。请使用基于整数或 StringBigDecimalBigDecimalBigDecimal时需谨慎,避免用于大量数学计算。

总结


BigDecimal。

  2,如果数据计算需要进行四色五入到整数,值加0.5的办法处理。

  3,对精度要求不高的环境下,比如测量值,允许存在误差且float和double导致的误差在其范围内。float和double数据原型是比较好的选择。