浅色年华的gravatar头像
浅色年华 2017-07-11 16:50:48
java中进行高精度精准计算

今天在做接口传保费的时候出现了一个奇怪的问题,double类型保费变成了一大长串的非精准保费,甚至奇怪,难道是java的bug?最后通过度娘找到了答案

话不多说,先看如下代码

public final class Person {
    public static void main(String[] args) {
        double a1 = 0.06;
        double a2 = 0.01;
        System.out.println(a1);
        System.out.println(a2);
        System.out.println(a2 + a1);
    }
}

结果并不是0.07,而是0.06999999999999999

    你认为你看错了,但结果却是是这样的。问题在哪里呢?原因在于我们的计算机是二进制的。浮点数没有办法是用二进制进行精确表示。我们的CPU表示浮点数由两个部分组成:指数和尾数,这样的表示方法一般都会失去一定的精确度,有些浮点数运算也会产生一定的误差。如:2.4的二进制表示并非就是精确的2.4。反而最为接近的二进制表示是 2.3999999999999999。浮点数的值实际上是由一个特定的数学公式计算得到的。

    其实Java的float只能用来进行科学计算或工程计算,在大多数的商业计算中,一般采用java.math.BigDecimal类来进行精确计算。

如何使用这个BigDecimal呢,拢共分三步,

一.float或者double变量构建BigDecimal对象

构建有两种方法:1.BigDecimal b1 = new BigDecimal(xxx); xxx可以是double类型,也可以是string类型

                              2.BigDecimal b2 = BigDecimal.valueOf(xxx); xxx 只能是数值类型

注意:推荐使用第一种方法,并采用string类型进行构建。否则还是会出现2.0809999999999的情况。

二.通过调用BigDecimal的加,减,乘,除等相应的方法进行算术运算

public BigDecimal add(BigDecimal value);                        //加法  
public BigDecimal subtract(BigDecimal value);                   //减法   
public BigDecimal multiply(BigDecimal value);                   //乘法  
public BigDecimal divide(BigDecimal value);                     //除法 

三.把BigDecimal对象转换成floatdoubleint等类型

        double a1 = b2.doubleValue();
        float a2 = b2.floatValue();

直接通过BigDecimal 进行计算比较麻烦,可以封装一层,简化使用


打赏
最近浏览
1248612588  LV1 2019年10月22日
youwuzuichen  LV10 2019年10月4日
a917480631 2019年3月8日
暂无贡献等级
1486780197  LV2 2018年11月10日
zyl  LV34 2018年6月29日
17600364495  LV1 2018年5月23日
smile2017  LV5 2018年2月16日
wgc_jy  LV21 2018年2月2日
a3870764722a  LV22 2017年10月18日
无名指  LV1 2017年10月18日
顶部 客服 微信二维码 底部
>扫描二维码关注最代码为好友扫描二维码关注最代码为好友