java计算金额保留两位小数精确到分(四舍六入五成双)

四舍六入五成双:

  四舍六入五成双是一种比较精确比较科学的计数保留法,是一种数字修约规则。

  对于位数很多的近似数,当有效位数确定后,其后面多余的数字应该舍去,只保留有效数字最末一位,这种修约(舍入)规则是"四舍六入五成双",也即"4舍6入5凑偶"这里"四"是指≤4 时舍去,"六"是指≥6时进上,"五"指的是根据5后面的数字来定,当5后有数时,舍5入1;当5后无有效数字时,需要分两种情况来讲:①5前为奇数,舍5入1;②5前为偶数,舍5不进。(0是偶数)

  从统计学的角度,"四舍六入五成双"比"四舍五入"要科学,在大量运算时,它使舍入后的结果误差的均值趋于零,而不是像四舍五入那样逢五就入,导致结果偏向大数,使得误差产生积累进而产生系统误差,"四舍六入五成双"使测量结果受到舍入误差的影响降到最低。

  在实际情况下,大部分交易的手续费是按单笔计算的,每一笔都对应一个手续费。

  例如费率为千分之三,交易1000元,手续费3元,实际到帐997元。交易255元,手续费 255 * 0.003 = 0.765 元。

  但是一般做交易时金额都是精确到分的,采用四舍六入五成双方法保留小数点后两位,所以这里手续费是0.76,实际到帐254.24元。

下边是java工具类:

传入返回参数类型都是String

public class StringAmountCalUtil {
    /**
     * @Description: 整数相除结果转换成指定位数的百分数
     * @param dividend : 被除数(分子)
     * @param divisor : 除数(分母)
     * @param digit : 保留几位小数
     * @return String
     */
    public static String getPercent(int dividend,int divisor,int digit) {
        Float result = (float)dividend/(float)divisor;
        if (result.isNaN()) {
            return "--";
        }else {
            //获取格式化对象
            NumberFormat nt = NumberFormat.getPercentInstance();
            //设置百分数精确度,即保留几位小数
            nt.setMinimumFractionDigits(digit);
            String finalResult = nt.format(result);
            return finalResult;
        }
    }

    /**
     * 两个数相加
     * @param str1
     * @param str2
     * @return
     */
    public static String add(String str1,String str2) {
        try {
            return new BigDecimal(str1).add(new BigDecimal(str2)).toPlainString();
        }catch (Exception e){
            return null;
        }
    }

    /**
     * 两个数相乘
     * @param str1
     * @param str2
     * @return
     */
    public static String multiply(String str1,String str2) {
        try {
            return new BigDecimal(str1).multiply(new BigDecimal(str2)).toPlainString();
        }catch (Exception e){
            return null;
        }
    }
    
    /**
     * 两个数相减
     * @param str1
     * @param str2
     * @return
     */
    public static String subtract(String str1,String str2) {
        try {
            return new BigDecimal(str1).subtract(new BigDecimal(str2)).toPlainString();
        }catch (Exception e){
            return null;
        }
    }
    
    /**
     * 两个数相除
     * @param str1
     * @param str2
     * @return
     */
    public static String divide(String str1,String str2) {
        try {
            return new BigDecimal(str1).divide(new BigDecimal(str2),5).toPlainString();
        }catch (Exception e){
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 四舍六入五五成双
     * @param str
     */
    public static String FourUpSixInto(String str){
        BigDecimal b1 = new BigDecimal(str);
        BigDecimal b2 = b1.setScale(2, BigDecimal.ROUND_HALF_EVEN);
        return b2.toString();
    }
}

public static void main(String [] args) {
  String jine = "255.00";
  String feilv = "0.003";
  String shouxufei = StringUtil.FourUpSixInto(StringUtil.multiply(jine, feilv));
  String realMoney = StringUtil.subtract(jine, shouxufei);
  System.out.println("交易金额["+jine+"]\n费率["+feilv+"]\n手续费["+shouxufei+"]\n到帐金额["+realMoney+"]\n");
}

运行结果:

交易金额[255.00]
费率[0.003]
手续费[0.76]
到帐金额[254.24]

 

posted @ 2019-01-31 17:06  常新志  阅读(13945)  评论(0编辑  收藏  举报