当前位置:网站首页>double类型精度丢失问题以及解决方法

double类型精度丢失问题以及解决方法

2022-07-23 09:58:00 ErwinNakajima

1、double类型精度丢失问题:

(1)加法运算。

public static void main(String[] args) {
	double number1 = 1;
	double number2 = 20.2;
	double number3 = 300.03;
	double result = number1 + number2 + number3;
	System.out.println("使用double运算结果: "+result);
}

打印结果如下:

        使用double运算结果: 321.22999999999996。。。

(2)乘法运算。

public static void main(String[] args) {
    double a = 152.70;
    System.out.println(a);
    System.out.println(a * 100);//15280.000000000002
    System.out.println(Math.round(a * 100));//还凑合
 
    double b = 152.70;
    System.out.println(b);
    System.out.println(b * 100);//15269.999999999998
    System.out.println((int)(b * 100));//15269 错误!!!不是想要的
}

然后把15280.000000000002 - 15280 = 1.8189894035458565E-12这个结果返回给了前端, 

前端拿去和0比较, 结果就炸了

原因:就是double的精度问题, 单个double数可能就有损失精度,,多个double数运算(减法和乘法都输入加法)可能导致损失的精度更多。。。

(3)减法运算。

double d1 = 2.11;
double d2 = 2.10;
System.out.println( d1 - d2);

口算结果是0.01。可是用程序执行出来的结果却出乎意料,执行结果为0.009999999999999787。

问题解决

转换为BigDecimal对象之后再进行加减乘除操作,这样精度就不会出现问题了。这也是为什么有关金钱数据存储都使用BigDecimal。

        处理double类型数据的加、减、乘、除运算时,使用如下方法:

package com.phone.common_library.manager;

import java.math.BigDecimal;

public class BigDecimalManager {

    /**
     * 加法运算
     * @param m1
     * @param m2
     * @return  不加doubleValue()则, 返回BigDecimal对象
     */
    public static double additionDouble(double m1, double m2) {
        BigDecimal p1 = new BigDecimal(Double.toString(m1));
        BigDecimal p2 = new BigDecimal(Double.toString(m2));
        return p1.add(p2).doubleValue();
    }

    /**
     * 减法运算
     * @param m1
     * @param m2
     * @return  不加doubleValue()则, 返回BigDecimal对象
     */
    public static double subtractionDouble(double m1, double m2) {
        BigDecimal p1 = new BigDecimal(Double.toString(m1));
        BigDecimal p2 = new BigDecimal(Double.toString(m2));
        return p1.subtract(p2).doubleValue();
    }

    /**
     * 乘法运算
     * @param m1
     * @param m2
     * @return  不加doubleValue()则, 返回BigDecimal对象
     */
    public static double multiplicationDouble(double m1, double m2) {
        BigDecimal p1 = new BigDecimal(Double.toString(m1));
        BigDecimal p2 = new BigDecimal(Double.toString(m2));
        return p1.multiply(p2).doubleValue();
    }

    /**
     * 除法运算
     * @param   m1
     * @param   m2
     * @param   scale
     * @return  不加doubleValue()则, 返回BigDecimal对象
     */
    public static double divisionDouble(double m1, double m2, int scale) {
        if (scale < 0) {
            throw new IllegalArgumentException("Parameter error");
        }
        BigDecimal p1 = new BigDecimal(Double.toString(m1));
        BigDecimal p2 = new BigDecimal(Double.toString(m2));
        return p1.divide(p2, scale, BigDecimal.ROUND_HALF_UP).doubleValue();
    }

}

·测试、验证问题是否解决:

public static void main(String[] args) {
	double result1 = additionDouble(1, 20.2);
	double result2 = additionDouble(result1, 300.03);
	System.out.println("使用BigDecimal运算结果:" + result2);
}

结果如下: 

使用BigDecimal运算结果:321.23

完美解决了double类型数据加减操作时精度丢失的问题。 

如对此有疑问,请联系qq1164688204。

推荐Android开源项目

项目功能介绍:RxJava2和Retrofit2项目,添加自动管理token功能,添加RxJava2生命周期管理,使用App架构设计是MVP模式和MVVM模式,同时使用组件化,部分代码使用Kotlin,此项目持续维护中。

项目地址:https://gitee.com/urasaki/RxJava2AndRetrofit2

原网站

版权声明
本文为[ErwinNakajima]所创,转载请带上原文链接,感谢
https://blog.csdn.net/NakajimaFN/article/details/125912091