浅色年华的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 进行计算比较麻烦,可以封装一层,简化使用


打赏

分享到:

最近浏览
17600364495 LV15月23日
星星
smile2017 LV32月16日
星星星星星星
wgc_jy LV202月2日
太阳月亮
a3870764722a LV212017年10月18日
太阳月亮星星
无名指 LV12017年10月18日
星星
zuiDMxin2017年10月12日
暂无贡献等级
373717096 LV172017年9月22日
太阳星星
wcy5555 LV62017年9月22日
月亮星星星星
toney_shen LV12017年9月7日
星星
q28238652017年9月6日
暂无贡献等级
顶部客服微信二维码底部
>扫描二维码关注最代码为好友扫描二维码关注最代码为好友