第二章 Java浮點數精確計算


1、實際意義

在實際開發中,如果需要進行float或double的精確計算(尤其是財務計算),直接使用float或double是不行的(具體的例子看下邊的代碼的main方法的測試結果),需要使用BigDecimal。

 

2、代碼

package com.xxx.util;

import java.math.BigDecimal;

/**
 * 浮點數精准算法
 */
public class BigDecimalArithUtil {

    private static final int DIV_SCALE = 10;//除法精度(除不盡時保留10為小數)
    
    /** 小數精確加法  */
    public static double add(double d1,double d2)
    {
        BigDecimal bd1 = BigDecimal.valueOf(d1);
        BigDecimal bd2 = BigDecimal.valueOf(d2);
        return bd1.add(bd2).doubleValue();
    }
    
    /** 小數精確減法  */
    public static double sub(double d1,double d2)
    {
        BigDecimal bd1 = BigDecimal.valueOf(d1);
        BigDecimal bd2 = BigDecimal.valueOf(d2);
        return bd1.subtract(bd2).doubleValue();
    }
    
    /** 小數精確乘法  */
    public static double mul(double d1,double d2)
    {
        BigDecimal bd1 = BigDecimal.valueOf(d1);
        BigDecimal bd2 = BigDecimal.valueOf(d2);
        return bd1.multiply(bd2).doubleValue();
    }
    
    /** 小數精確除法   */
    public static double div(double d1,double d2)
    {
        BigDecimal bd1 = BigDecimal.valueOf(d1);
        BigDecimal bd2 = BigDecimal.valueOf(d2);
        /*
         * 當除不盡時,以四舍五入的方式(關於除不盡后的值的處理方式有很多種)保留小數點后10位小數
         */
        return bd1.divide(bd2, DIV_SCALE, BigDecimal.ROUND_HALF_UP).doubleValue();
    }
    
    public static void main(String[] args)
    {
        //測試加法
        System.out.println("0.05+0.01="+BigDecimalArithUtil.add(0.05,0.01));
        System.out.println("0.05+0.01="+(0.05+0.01));
        //測試減法
        System.out.println("1.0-0.42="+BigDecimalArithUtil.sub(1.0,0.42));
        System.out.println("1.0-0.42="+(1.0-0.42));
        //測試乘法
        System.out.println("4.015*100="+BigDecimalArithUtil.mul(4.015,100));
        System.out.println("4.015*100="+(4.015*100));
        //測試除法
        System.out.println("123.3/100="+BigDecimalArithUtil.div(123.3,100));
        System.out.println("123.3/100="+(123.3/100));
    }

}
View Code

 

3、注意點

  • 上邊的程序我用的是BigDecimal.valueOf(double x)來將double型的x封裝成BigDecimal,查看源碼如下:
        /**
         * 注意:這通常是將double和float轉換為一個BigDecimal的最好方式
         */
        public static BigDecimal valueOf(double val) {
            return new BigDecimal(Double.toString(val));
        }
    View Code

    在這里直接先將double轉換為了String,然后使用如下構造方法再將String轉換為BigDecimal

     public BigDecimal(String val)

    這是最好的做法。如果使用的是直接將double或float轉換為BigDecimal的方式,也就是說使用的如下構造器,那么將可能得不到精確結果。(看注釋)這一點可以用10.02*10.02來證明。

        /**
         * 注意:The results of this constructor can be somewhat unpredictable.
         * 該構造器的結果有時是不准確的
         */
        public BigDecimal(double val)
    View Code
  • 在實際使用中還可能使用int和long來進行浮點數的精確計算(具體做法:將浮點數先乘以相應的倍數轉化為int(<=9位十進制數)或long(<=18位十進制數),計算之后再除以之前的倍數,得出結果),而且該種方式的性能會更高,具體的int、long和BigDecimal各自的使用看《Effective Java(第二版)》第48條。
  • 需要指出的是,在實際開發中,BigDecimal的性能差的問題基本可以忽略,是浮點數精確計算的首選,而且根據上一條來看,如果將浮點數轉化后的整數大於18位的話,也必須用BigDecimal


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM