金錢還在使用 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));
    }

}

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