BigDecimal

有空發表於2024-11-15

不精確的情況:

public class BigDecimalDemo1 {
    public static void main(String[] args) {
        System.out.println(0.09 + 0.01);   // 0.09999999999999999
        System.out.println(0.216 - 0.1);   // 0.11599999999999999
        System.out.println(0.226 * 0.01);  // 0.0022600000000000003
        System.out.println(0.09 / 0.1);    // 0.8999999999999999
    }
}

有些小數可能有很多位:

BigDecimal
圖1

浮點型別所佔用的位數是有限的:

BigDecimal
圖2

如果浮點數的二進位制位數太多, 超過了位數的限制, 則只能捨棄, 從而導致資料不精確.

BigDecimal 所在的包: java.math

BigDecimal
圖3

程式示例:

public class Demo {
    public static void main(String[] args) {
        /*
            構造方法獲取 BigDecimal 物件
            public BigDecimal(double val) public BigDecimal(string val)

            靜態方法獲取 BigDecimal 物件
            public static BigDecimal valuef(double val)
        */

        // 1. 透過傳遞 double 型別的小數來建立物件
        // 細節:
        // 這種方式有可能是不精確的, 所以不建議使用
        BigDecimal bd1 = new BigDecimal(0.01);
        BigDecimal bd2 = new BigDecimal(0.09);

        System.out.println(bd1);  // 0.01000000000000000020816681711721685132943093776702880859375
        System.out.println(bd2);  // 0.0899999999999999966693309261245303787291049957275390625

        // 透過傳遞字串表示的小數來建立物件
        BigDecimal bd3 = new BigDecimal("0.01");
        BigDecimal bd4 = new BigDecimal("0.09");
        BigDecimal bd5 = bd3.add(bd4);
        System.out.println(bd3);  // 0.01
        System.out.println(bd4);  // 0.09
        System.out.println(bd5);  // 0.10
    }
}

程式示例:

public class Demo {
    public static void main(String[] args) {
        /*
            構造方法獲取 BigDecimal 物件
            public BigDecimal(double val) public BigDecimal(string val)

            靜態方法獲取 BigDecimal 物件
            public static BigDecimal valuef(double val)
        */

        // 3. 透過靜態方法獲取物件
        // 細節:
        // 1. 如果要表示的數字不大, 沒有超出 double 的取值範圍, 建議使用靜態方法
        // 2. 如果要表示的數字比較大, 超出了 double 的取值範圍, 建議使用構造方法
        // 3. 如果我們傳遞的是 0 ~ 10 之間的整數, 包含 0, 包含 10, 那麼方法會返回已經建立好的物件, 不會重新 new
        BigDecimal bd6 = BigDecimal.valueOf(10.0);
        BigDecimal bd7 = BigDecimal.valueOf(10.0);
        System.out.println(bd6 == bd7);  // false

        BigDecimal bd66 = BigDecimal.valueOf(10);
        BigDecimal bd77 = BigDecimal.valueOf(10);
        System.out.println(bd66 == bd77);  // true
    }
}

引數為 double 的 valueOf() 方法:

圖片名稱

引數為 long 的 valueOf() 方法:

圖片名稱

檢視 ZERO_THROUGH_TEN 陣列:

圖片名稱

BigDecimal 的成員方法:

圖片名稱

程式示例:

import java.math.BigDecimal;
import java.math.RoundingMode;

public class Demo3 {
    public static void main(String[] args) {
         /*
            public BigDecimal add(BigDecimal val) 加法
            public BigDecimal subtract(BigDecimal val) 減法
            public BigDecimal multiply(BigDecimal val) 乘法
            public BigDecimal divide(BigDecimal val) 除法
            public BigDecimal divide(BigDecimal val, 精確幾位, 舍入模式)除法
        */
        // 1.加法
        BigDecimal bd1 = BigDecimal.valueOf(10.);
        BigDecimal bd2 = BigDecimal.valueOf(3.0);
        BigDecimal bd3 = bd1.add(bd2);
        System.out.println(bd3);  // 12.0

        // 2.減法
        BigDecimal bd4 = bd1.subtract(bd2);
        System.out.println(bd4);  // 8.0

        // 3.乘法
        BigDecimal bd5 = bd1.multiply(bd2);
        System.out.println(bd5);  // 20.00

        // 4.除法
        BigDecimal bd6 = bd1.divide(bd2, 2, RoundingMode.HALF_UP);  // 四捨五入
        BigDecimal bd7 = bd1.divide(bd2, 2, BigDecimal.ROUND_HALF_UP);
        System.out.println(bd6);  // 3.33
        System.out.println(bd7);  // 3.33
    }
}
圖片名稱 圖片名稱

用打斷點的方式檢視:

public class Demo4 {
    public static void main(String[] args) {
        BigDecimal bd1 = BigDecimal.valueOf(0.226);
        BigDecimal bd2 = BigDecimal.valueOf(123.226);
        BigDecimal bd3 = BigDecimal.valueOf(-1.5);
    }
}
圖片名稱

注意這些陣列是 byte 型別的.

BigDecimal 也是有上限的. 但是實際電腦記憶體是不可能達到這麼大的值的, 所以可以認為是無限大的.

相關文章