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

分享到:

最近浏览
373717096昨天
最代码贡献等级说明
wcy5555昨天
最代码贡献等级说明
toney_shen9月7日
最代码贡献等级说明
q28238659月6日
暂无贡献等级
junwuxie9月1日
最代码贡献等级说明
庸人自扰8月17日
暂无贡献等级
tiger19808月16日
最代码贡献等级说明
zhaoshuting8月10日
最代码贡献等级说明
醉美猴王 LV28月8日
最代码贡献等级说明
JiangBigPan8月2日
最代码贡献等级说明
yulinfeng8月2日
最代码贡献等级说明
a10166647368月2日
最代码贡献等级说明
sc9368668月1日
暂无贡献等级
wsh5644940628月1日
最代码贡献等级说明
暂无贡献等级
zsdnishishui7月30日
最代码贡献等级说明
暂无贡献等级
白吃水泥7月28日
暂无贡献等级
Watson7月27日
最代码贡献等级说明
顶部客服微信二维码底部
>扫描二维码关注最代码为好友扫描二维码关注最代码为好友