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


打赏

分享到:

最近浏览
a3870764722a10月18日
最代码贡献等级说明
无名指10月18日
暂无贡献等级
zuiDMxin10月12日
暂无贡献等级
3737170969月22日
最代码贡献等级说明
wcy55559月22日
最代码贡献等级说明
toney_shen9月7日
最代码贡献等级说明
q28238659月6日
暂无贡献等级
junwuxie9月1日
最代码贡献等级说明
庸人自扰8月17日
暂无贡献等级
小恶魔8月16日
最代码贡献等级说明
zhaoshuting8月10日
最代码贡献等级说明
醉美猴王 LV28月8日
最代码贡献等级说明
JiangBigPan8月2日
最代码贡献等级说明
yulinfeng8月2日
最代码贡献等级说明
a10166647368月2日
最代码贡献等级说明
sc9368668月1日
暂无贡献等级
wsh5644940628月1日
最代码贡献等级说明
暂无贡献等级
zsdnishishui7月30日
最代码贡献等级说明
暂无贡献等级
顶部客服微信二维码底部
>扫描二维码关注最代码为好友扫描二维码关注最代码为好友