JAVA-精确计算时的陷阱

来源:互联网 发布:盗梦三国龙将无双java 编辑:程序博客网 时间:2024/05/06 07:13

java.math包中有个BigDecimal类,通过这个类可以进行精确计算. 我们知道BigDecimal有个setScale(int 精度,int 舍入模式)方法,随之而来问题出现了,当运行如下代码时:

却惊奇地打印出结果:

0.82

 

Oh My God,对0.825进行小数点后保留2位有效数字,四舍五入后结果应该是:0.83。为什么打印结果是0.82

 

没错BigDecimaldouble val)这个构造器欺骗了我们,它使用了0.825的近似值(0.8249999999999……)来构造BigDecimal

为什么会这样?

 

原来JAVA存储浮点数(floatdouble)时,使用的是IEEE754标准,每个浮点数使用的是 符号位、阶码、尾数来表示:

````````符号位  阶码   尾数    长度
float     1      8      23       32
double    1      11     52       64

通过这种方法保存在计算机里面的浮点数,实际上是它的近似值。举例说明问题:

定义一个double 38414.4,将它转换为16进制。我们先计算整数部分38414等于960E。小数处理:0.4=0*0.5+0.25*1+0.0625*0+……,实际上我们永远计算不完。

结论:当我们定义一个浮点数时,请告诉自己,我们定义只不过是这个浮点数的近似值,即0.825!=0.825

 

为了避免这个问题,我们应该使用如下方法:

使用BigDecimalString val)构造器,这段代码运行的结果是:0.83

 

由此可见BigDecimaldouble val)这个构造器完全就是一个陷阱。

原创粉丝点击