BigDecimal浮点精度加减乘除运算

package com.shopping.test;

import java.math.BigDecimal;

/**
 * 精确的浮点运算
 * 为什么要使用BigDecimal类型呢?
 * BigDecimal可以进行超过16位有效位的数值的准确运算,而我们所熟知的浮点型float的精度为6-7位有效数字,Double类型则为15-16位有效数字。
 * 这不是关键,浮点型变量在进行计算的时候会出现丢失精度的问题,所以我们为了保证数据的准确性,需要用到BigDecimal去进行高精度的运算。
 */
public class OperationUtil {

    private  static final  int DEF_DIV_SCALE=10;//默认除法运算精度
    private OperationUtil(){
    }

    /**
     * 精确的加法运算
     * @param v1 被加数
     * @param v2 加数
     * @return 两个参数的和
     */
    public static  double add(double v1 ,double v2){
        BigDecimal b1 = new BigDecimal(Double.toString(v1));
        BigDecimal b2 = new BigDecimal(Double.toString(v2));
        return b1.add(b2).doubleValue();
    }


    /**
     * 精确的减法运算
     * @param v1 被减数
     * @param v2 减数
     * @return 两个参数的差
     */
    public static  double sub(double v1 ,double v2){
        BigDecimal b1 = new BigDecimal(Double.toString(v1));
        BigDecimal b2 = new BigDecimal(Double.toString(v2));
        return b1.subtract(b2).doubleValue();
    }

    /**
     * 精确的乘法运算
     * @param v1 被乘数
     * @param v2 乘数
     * @return 两个参数的积
     */
    public static  double mul(double v1 ,double v2){
        BigDecimal b1 = new BigDecimal(Double.toString(v1));
        BigDecimal b2 = new BigDecimal(Double.toString(v2));
        return b1.multiply(b2).doubleValue();
    }


    /**
     * 相对精确的除法运算
     * 当除不尽时候精确到小数点后10位,以后的数字四舍五入
     * @param v1 被除数
     * @param v2 除数
     * @return 两个参数的商
     */
    public static  double div(double v1 ,double v2){
        return div(v1, v2,DEF_DIV_SCALE);
    }


    /**
     * 提供精确的除法运算
     * 当除不尽时候精确到小数点后 scale 位,以后的数字四舍五入
     * @param v1 被除数
     * @param v2 除数
     * @param scale 精确到小数点后几位
     * @return 两个参数的商
     */
    public static  double div(double v1 ,double v2,int scale){
        if (scale<0){
        throw new IllegalArgumentException("The scale must be a positive or zero ");
        }
        BigDecimal b1 = new BigDecimal(Double.toString(v1));
        BigDecimal b2 = new BigDecimal(Double.toString(v2));
        return b2.divide(b1,scale,BigDecimal.ROUND_HALF_UP).doubleValue();
    }


    /**
     * 提供精确到小数位的数字四舍五入
     * @param v 需要四舍五入的数字
     * @param scale 小数点后保留几位
     * @return 四舍五入后的结果
     */
    public static  double round(double v ,int scale){
        if (scale<0){
            throw new IllegalArgumentException("The scale must be a positive or zero ");
        }
        BigDecimal b = new BigDecimal(Double.toString(v));
        BigDecimal one = new BigDecimal(1);
        return b.divide(one,scale,BigDecimal.ROUND_HALF_UP).doubleValue();
    }


    public static void main(String[] args){

        System.out.println(OperationUtil.round (3.3334111,3));
        System.out.println(OperationUtil.round (3.3335111,3));

    }



}

 

当然不同的场景所需要的算法不一样

posted @ 2019-08-22 17:34  坠落凡尘的魔鬼  阅读(468)  评论(0编辑  收藏  举报