金钱还在使用 Double吗?要使用 BigDecimal

Java中的简单浮点数类型float和double不能够进行运算,或者运算会丢失精度,不光是Java,在其它很多编程语言中也有这样的问题。在大多数情况下,计算的结果是准确的,float和double只能用来做科学计算或者是工程计算,在商业计算中我们要用 java.math.BigDecimal

package com.xinzhi.util;
/**
 * 引入BigDecimal工具类
 */
import com.sun.org.apache.regexp.internal.RE;
import com.xinzhi.constant.FinanceConstant;

import java.math.BigDecimal;
import java.text.DecimalFormat;

/**
 * @author 空巷
 * 金钱计算工具类
 */
public class ArithUtil {

    //千位分隔符 方便查看金额具体大小
    public static final String BIG_NUM_FMT_COMMA = "#,###,###,###,###,###,##0.00";

    //不带千位分隔符
    public static final String BIG_NUM_FMT = "##################0.00";

    //100常量
    public static final String BIG_NUM_HUNDRED = "100";

    //保留两位小数
    public static final int BIG_NUM_SCALE = 2;

    //一年的还款利率  利率自定义 可更改
    public static final double ONE_YEAR_INTEREST_RATE = 0.0531;

    private ArithUtil(){}
    /**
     * 精确加法工具类
     * @param v1 加数
     * @param v2 被加数
     * @return ;两个参数的和
     */
    public static BigDecimal add(String v1, String v2){
        BigDecimal b1 = new BigDecimal(v1);
        BigDecimal b2 = new BigDecimal(v2);
        return b1.add(b2);
    }

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

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

    /**
     * 精确除法运算
     * @param v1 除数
     * @param v2 被除数
     * @param scale 表示精确小数点后几位
     * @return 两个参数的商
     * @throws IllegalAccessException
     */
    public static BigDecimal div(String v1, String v2, int scale){
        if (scale < 0){
            try {
                throw new IllegalAccessException(
                        // 如果scale小于0,则抛出异常“比例必须是一个正整数或零”
                        "The scale must be a positive integer or zero");
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
        BigDecimal b1 = new BigDecimal(v1);
        BigDecimal b2 = new BigDecimal(v2);
        return b1.divide(b2,scale,BigDecimal.ROUND_HALF_UP);
    }

    /**
     * 保留小数位
     * @param v
     * @param scale
     * @return
     * @throws IllegalAccessException
     */
    public static BigDecimal round(String v, int scale){
        if (scale < 0){
            try {
                throw new IllegalAccessException(
                        // 如果scale小于0,则抛出异常“比例必须是一个正整数或零”
                        "The scale must be a positive integer or zero");
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
        BigDecimal b1 = new BigDecimal(v);
        BigDecimal b2 = new BigDecimal("1");
        return b1.divide(b2,scale,BigDecimal.ROUND_HALF_UP);
    }

    /**
     * 分转换成元
     * @param v
     * @return
     */
    public static BigDecimal penny2dollar(String v){
        //保留两位小数
        BigDecimal s = ArithUtil.div(v,"100",2);
        return s;
    }

    /**
     * 元转换成分
     * @param v
     * @return
     */
    public static BigDecimal dollar2penny(String v){
        return mul(v, "100");
    }

    /**
     * 格式化金额
     * 千位分隔符 方便查看金额具体大小 BIG_NUM_FMT = "#,###,###,###,###,###,##0.00"
     * 精确两位小数 .99 -> 0.99
     *             1111111.985 -> 1,111,111.99
     * @param v
     * @return
     */
    public static String formatNumber(String v){
        return formatNumber(v, FinanceConstant.BIG_NUM_FMT_COMMA);
    }

    /**
     * 格式化金额
     * @param v
     * @param pattern BigNum类中的常量 BIG_NUM_FMT_COMMA,BIG_NUM_FMT
     * @return
     */
    public static String formatNumber(String v,String pattern) {
        return new DecimalFormat(pattern).format(new BigDecimal(v));
    }

    /**
     * 一次还本付息法
     * 计算到期一次还本付息金额
     * 到期一次还本付息额=贷款本金×[1+年利率(%)] (贷款期为一年)
     * 到期一次还本付息额=贷款本金×[1+月利率(‰)×贷款期(月)] (贷款期不到一年)
     * @param v1
     * @return
     */
    public static String singleUseRepayment(String v1,int month){
        BigDecimal b1 = new BigDecimal(v1);
        //当分期一年时的应偿还金额
        if (month == 12){
            BigDecimal multiply = b1.multiply(BigDecimal.valueOf(1 + FinanceConstant.ONE_YEAR_INTEREST_RATE));
            //保留两位小数
            BigDecimal round = ArithUtil.round(String.valueOf(multiply), 2);
            //格式化金额
            return ArithUtil.formatNumber(String.valueOf(round));
        }else{
            //计算月利率
            BigDecimal b2 = new BigDecimal(1 + FinanceConstant.ONE_YEAR_INTEREST_RATE / 12 * month);
            //保留两位小数
            BigDecimal round = ArithUtil.round(String.valueOf(b1.multiply(b2)), 2);
            //格式化金额
            return ArithUtil.formatNumber(String.valueOf(round));
        }
    }

//测试方法
    public static void main(String[] args) {
//        System.out.println(ArithUtil.add("1.99","20.999"));
//        System.out.println(ArithUtil.sub("1.99","20.999"));
        String s = "1111111.985";
        String a = ArithUtil.formatNumber(s);
        System.out.println(ArithUtil.singleUseRepayment("5000",11));
//        System.out.println(s);
//        System.out.println(a);
        System.out.println(ArithUtil.round("5000.2343423",2));
    }

}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章