BigDecimal加減乘除計算


一、簡述

java.math.BigDecimal
不可變的、任意精度的有符號十進制數。BigDecimal 由任意精度的整數非標度值(unscaledValue)和32位的整數標度(scale)組成。其值為該數的非標度值乘以10的負scale次冪,即為(unscaledValue * 10-scale)。與之相關的還有兩個類:

  1. java.math.MathContext
    該對象是封裝上下文設置的不可變對象,它描述數字運算符的某些規則,如數據的精度,舍入方式等。

  2. java.math.RoundingMode
    這是一種枚舉類型,定義了很多常用的數據舍入方式。這個類用起來還是很比較復雜的,原因在於舍入模式,數據運算規則太多,不是數學專業出身的人看着中文API都難以理解,這些規則在實際中使用的時候再翻閱都來得及。

二、方法介紹

在銀行、帳戶、計費等領域,BigDecimal提供了精確的數值計算。對Bigdecimal類型值進行加減乘除絕對值的運算,其實就是Bigdecimal的類方法的一些調用。

    • 加法:add()函數
    • 減法:subtract()函數
    • 乘法:multiply()函數
    • 除法:divide()函數
    • 絕對值:abs()函數
    • al valueSec = new BigDecimal(1000000);
              BigDecimal valueThi = new BigDecimal(-1000000);
      
              //盡量用字符串的形式初始化
              BigDecimal stringFir = new BigDecimal("0.005");
              BigDecimal stringSec = new BigDecimal("1000000");
              BigDecimal stringThi = new BigDecimal("-1000000");
      
              //加法
              BigDecimal addVal = valueFir.add(valueSec);
              System.out.println("加法用value結果:" + addVal);
              BigDecimal addStr = stringFir.add(stringSec);
              System.out.println("加法用string結果:" + addStr);
      
              //減法
              BigDecimal subtractVal = valueFir.subtract(valueSec);
              System.out.println("減法value結果:" + subtractVal);
              BigDecimal subtractStr = stringFir.subtract(stringSec);
              System.out.println("減法用string結果:" + subtractStr);
      
              //乘法
              BigDecimal multiplyVal = valueFir.multiply(valueSec);
              System.out.println("乘法用value結果:" + multiplyVal);
              BigDecimal multiplyStr = stringFir.multiply(stringSec);
              System.out.println("乘法用string結果:" + multiplyStr);
      
              //絕對值
              BigDecimal absVal = valueThi.abs();
              System.out.println("絕對值用value結果:" + absVal);
              BigDecimal absStr = stringThi.abs();
              System.out.println("絕對值用string結果:" + absStr);
      
              //除法
              BigDecimal divideVal = valueSec.divide(valueFir, 20, BigDecimal.ROUND_HALF_UP);
              System.out.println("除法用value結果:" + divideVal);
              BigDecimal divideStr = stringSec.divide(stringFir, 20, BigDecimal.ROUND_HALF_UP);
              System.out.println("除法用string結果:" + divideStr);
      
          }

      根據結果,初始化建議使用String

    •  

       

      三、注意

      1. System.out.println()中的數字默認是double類型的,double類型小數計算不精准。
      2. 使用BigDecimal類構造方法傳入double類型時,計算的結果也是不精確的。

      因為不是所有的浮點數都能夠被精確的表示成一個double 類型值,因此它會被表示成與它最接近的 double 類型的值。必須改用傳入String的構造方法。這一點在BigDecimal類的構造方法注釋中有說明。

      四、除法divide()

    • 使用除法函數在divide的時候要設置各種參數,要有除數、精確的小數位數和舍入模式,不然會出現報錯。源碼如下:

       

      例:

       public static void main(String[] args) {
             
              BigDecimal Dividend = new BigDecimal("1");
              BigDecimal divisor = new BigDecimal("3");
      
              BigDecimal res1 = Dividend.divide(divisor,3,BigDecimal.ROUND_UP);
              System.out.println("除法ROUND_UP:"+res1);
              BigDecimal res2 = Dividend.divide(divisor,3,BigDecimal.ROUND_DOWN);
              System.out.println("除法ROUND_DOWN:"+res2);
              BigDecimal res3 = Dividend.divide(divisor,3,BigDecimal.ROUND_CEILING);
              System.out.println("除法ROUND_CEILING:"+res3);
              BigDecimal res4 = Dividend.divide(divisor,3,BigDecimal.ROUND_FLOOR);
              System.out.println("除法ROUND_FLOOR:"+res4);
              BigDecimal res5 = Dividend.divide(divisor,3,BigDecimal.ROUND_HALF_UP);
              System.out.println("除法ROUND_HALF_UP:"+res5);
              BigDecimal res6 = Dividend.divide(divisor,3,BigDecimal.ROUND_HALF_DOWN);
              System.out.println("除法ROUND_HALF_DOWN:"+res6);
              BigDecimal res7 = Dividend.divide(divisor,3,BigDecimal.ROUND_HALF_EVEN);
              System.out.println("除法ROUND_HALF_EVEN:"+res7);
              BigDecimal res8 = Dividend.divide(divisor,3,BigDecimal.ROUND_UNNECESSARY);
              System.out.println("除法ROUND_UNNECESSARY:"+res8);
          }

      結果:

       

      舍入模式

      1. ROUND_UP

      舍入遠離零的舍入模式。在丟棄非零部分之前始終增加數字(始終對非零舍棄部分前面的數字加1)。注意,此舍入模式始終不會減少計算值的大小。

      1. ROUND_DOWN

      接近零的舍入模式。在丟棄某部分之前始終不增加數字(從不對舍棄部分前面的數字加1,即截短)。注意,此舍入模式始終不會增加計算值的大小。

      1. ROUND_CEILING

      接近正無窮大的舍入模式。如果 BigDecimal 為正,則舍入行為與 ROUND_UP 相同;如果為負,則舍入行為與 ROUND_DOWN 相同。注意,此舍入模式始終不會減少計算值。

      1. ROUND_FLOOR

      接近負無窮大的舍入模式。如果 BigDecimal 為正,則舍入行為與 ROUND_DOWN 相同;如果為負,則舍入行為與 ROUND_UP 相同。注意,此舍入模式始終不會增加計算值。

      1. ROUND_HALF_UP

      向“最接近的”數字舍入,如果與兩個相鄰數字的距離相等,則為向上舍入的舍入模式。如果舍棄部分 >= 0.5,則舍入行為與 ROUND_UP 相同;否則舍入行為與 ROUND_DOWN 相同。注意,這是我們大多數人在小學時就學過的舍入模式(四舍五入)。

      1. ROUND_HALF_DOWN

      向“最接近的”數字舍入,如果與兩個相鄰數字的距離相等,則為上舍入的舍入模式。如果舍棄部分 > 0.5,則舍入行為與 ROUND_UP 相同;否則舍入行為與 ROUND_DOWN 相同(五舍六入)。

      1. ROUND_HALF_EVEN

      向“最接近的”數字舍入,如果與兩個相鄰數字的距離相等,則向相鄰的偶數舍入。如果舍棄部分左邊的數字為奇數,則舍入行為與 ROUND_HALF_UP 相同;如果為偶數,則舍入行為與 ROUND_HALF_DOWN 相同。注意,在重復進行一系列計算時,此舍入模式可以將累加錯誤減到最小。此舍入模式也稱為“銀行家舍入法”,主要在美國使用。四舍六入,五分兩種情況。如果前一位為奇數,則入位,否則舍去。

      以下例子為保留小數點1位,那么這種舍入方式下的結果。

      1.15>1.2 1.25>1.2

      1. ROUND_UNNECESSARY

      斷言請求的操作具有精確的結果,因此不需要舍入。如果對獲得精確結果的操作指定此舍入模式,則拋出ArithmeticException。

       

       

       一般情況下,在進行數字的乘除的時候,最好的方式,是將數字轉成String類型,

       

      五、BigDecimal轉成int類型

      BigDecimal b=new BigDecimal(45.45);

      int a = b.intValue();


免責聲明!

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



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