<form id="dlljd"></form>
        <address id="dlljd"><address id="dlljd"><listing id="dlljd"></listing></address></address>

        <em id="dlljd"><form id="dlljd"></form></em>

          <address id="dlljd"></address>
            <noframes id="dlljd">

              聯系我們 - 廣告服務 - 聯系電話:
              您的當前位置: > 關注 > > 正文

              環球看點!BigDecimal詳細解析

              來源:CSDN 時間:2022-12-09 15:45:50

              簡介

              ? BigDecimal 由任意精度的整數非標度值 和32 位的整數標度 (scale) 組成。如果為零或正數,則標度是小數點后的位數。如果為負數,則將該數的非標度值乘以 10 的負scale 次冪。因此,BigDecimal表示的數值是(unscaledValue × 10-scale)。

              先運行一套代碼


              (相關資料圖)

              public static void main(String[] args)    {        System.out.println(0.2 + 0.1);        System.out.println(0.3 - 0.1);        System.out.println(0.2 * 0.1);        System.out.println(0.3 / 0.1);    }

              輸出效果

              0.300000000000000040.199999999999999980.0200000000000000042.9999999999999996

              原因

              我們的計算機是二進制的。浮點數沒有辦法是用二進制進行精確表示。我們的CPU表示浮點數由兩個部分組成:指數和尾數,這樣的表示方法一般都會失去一定的精確度,有些浮點數運算也會產生一定的誤差。如:2.4的二進制表示并非就是精確的2.4。反而最為接近的二進制表示是 2.3999999999999999。浮點數的值實際上是由一個特定的數學公式計算得到的。

              構造方法

              1.public BigDecimal(double val) 將double表示形式轉換為BigDecimal *不建議使用

              2.public BigDecimal(int val)  將int表示形式轉換成BigDecimal

              3.public BigDecimal(String val)  將String表示形式轉換成BigDecimal

              示例

              BigDecimal bigDecimal = new BigDecimal(2);BigDecimal bDouble = new BigDecimal(2.4);BigDecimal bString = new BigDecimal("2.4");System.out.println("bigDecimal=" + bigDecimal);System.out.println("bDouble=" + bDouble);System.out.println("bString=" + bString);

              輸出結果

              bigDecimal=2bDouble=2.399999999999999911182158029987476766109466552734375bString=2.4

              JDK的描述(原因)

              1、參數類型為double的構造方法的結果有一定的不可預知性。有人可能認為在Java中寫入newBigDecimal(0.1)所創建的BigDecimal正好等于 0.1(非標度值 1,其標度為 1),但是它實際上等于0.1000000000000000055511151231257827021181583404541015625。這是因為0.1無法準確地表示為 double(或者說對于該情況,不能表示為任何有限長度的二進制小數)。這樣,傳入到構造方法的值不會正好等于 0.1(雖然表面上等于該值)。

              ? 2、另一方面,String 構造方法是完全可預知的:寫入 newBigDecimal(“0.1”) 將創建一個 BigDecimal,它正好等于預期的 0.1。因此,比較而言,通常建議優先使用String構造方法。

              如果是確定用double,則可以用Double.toString(2.4),如下代碼

              BigDecimal bDouble1 = BigDecimal.valueOf(2.4);BigDecimal bDouble2 = new BigDecimal(Double.toString(2.4));System.out.println("bDouble1=" + bDouble1);System.out.println("bDouble2=" + bDouble2);

              輸出結果

              bDouble1=2.4bDouble2=2.4

              幾種常用函數

              加:BigDecimal add(BigDecimal augend)

              減:BigDecimal subtract(BigDecimal subtrahend)

              乘:BigDecimal multiply(BigDecimal multiplicand)

              除法:BigDecimal divide(BigDecimal divisor, int scale, int roundingMode)

              (BigDecimal divisor 除數, int scale 精確小數位, int roundingMode 舍入模式)

              絕對值:BigDecimal abs()

              例子代碼

              BigDecimal num1 = new BigDecimal(2.4);BigDecimal num2 = new BigDecimal(2);BigDecimal num3 = new BigDecimal(-2);//盡量用字符串的形式初始化BigDecimal num12 = new BigDecimal("2.4");BigDecimal num22 = new BigDecimal("2");BigDecimal num32 = new BigDecimal("-2");//加法BigDecimal result1 = num1.add(num2);BigDecimal result12 = num12.add(num22);//減法BigDecimal result2 = num1.subtract(num2);BigDecimal result22 = num12.subtract(num22);//乘法BigDecimal result3 = num1.multiply(num2);BigDecimal result32 = num12.multiply(num22);//絕對值BigDecimal result4 = num3.abs();BigDecimal result42 = num32.abs();//除法BigDecimal result5 = num2.divide(num1,20,BigDecimal.ROUND_HALF_UP);BigDecimal result52 = num22.divide(num12,20,BigDecimal.ROUND_HALF_UP);System.out.println("加法用value結果 result1:"+result1);System.out.println("加法用string結果 result12:"+result12);System.out.println("減法value結果:"+result2);System.out.println("減法用string結果:"+result22);System.out.println("乘法用value結果 result3:"+result3);System.out.println("乘法用string結果 result32:"+result32);System.out.println("絕對值用value結果 result4:"+result4);System.out.println("絕對值用string結果 result42:"+result42);System.out.println("除法用value結果 result5:"+result5);System.out.println("除法用string結果 result52:"+result52);

              輸出結果

              加法用value結果 result1:4.399999999999999911182158029987476766109466552734375加法用string結果 result12:4.4減法value結果:0.399999999999999911182158029987476766109466552734375減法用string結果:0.4乘法用value結果 result3:4.799999999999999822364316059974953532218933105468750乘法用string結果 result32:4.8絕對值用value結果 result4:2絕對值用string結果 result42:2除法用value結果 result5:0.83333333333333336417除法用string結果 result52:0.83333333333333333333

              除法的八種舍入模式

              1、ROUND_UP

              舍入遠離零的舍入模式。

              在丟棄非零部分之前始終增加數字(始終對非零舍棄部分前面的數字加1)。

              注意,此舍入模式始終不會減少計算值的大小。

              2、ROUND_DOWN

              接近零的舍入模式。

              在丟棄某部分之前始終不增加數字(從不對舍棄部分前面的數字加1,即截短)。

              注意,此舍入模式始終不會增加計算值的大小。

              3、ROUND_CEILING

              接近正無窮大的舍入模式。

              如果 BigDecimal 為正,則舍入行為與 ROUND_UP 相同;

              如果為負,則舍入行為與 ROUND_DOWN 相同。

              注意,此舍入模式始終不會減少計算值。

              4、ROUND_FLOOR

              接近負無窮大的舍入模式。

              如果 BigDecimal 為正,則舍入行為與 ROUND_DOWN 相同;

              如果為負,則舍入行為與 ROUND_UP 相同。

              注意,此舍入模式始終不會增加計算值。

              5、ROUND_HALF_UP

              向“最接近的”數字舍入,如果與兩個相鄰數字的距離相等,則為向上舍入的舍入模式。

              如果舍棄部分 >= 0.5,則舍入行為與 ROUND_UP 相同;否則舍入行為與 ROUND_DOWN 相同。

              注意,這是我們大多數人在小學時就學過的舍入模式(四舍五入)。

              6、ROUND_HALF_DOWN

              向“最接近的”數字舍入,如果與兩個相鄰數字的距離相等,則為上舍入的舍入模式。

              如果舍棄部分 > 0.5,則舍入行為與 ROUND_UP 相同;否則舍入行為與 ROUND_DOWN 相同(五舍六入)。

              7、ROUND_HALF_EVEN

              向“最接近的”數字舍入,如果與兩個相鄰數字的距離相等,則向相鄰的偶數舍入。

              如果舍棄部分左邊的數字為奇數,則舍入行為與 ROUND_HALF_UP 相同;

              如果為偶數,則舍入行為與 ROUND_HALF_DOWN 相同。

              注意,在重復進行一系列計算時,此舍入模式可以將累加錯誤減到最小。

              此舍入模式也稱為“銀行家舍入法”,主要在美國使用。四舍六入,五分兩種情況。

              如果前一位為奇數,則入位,否則舍去。

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

              1.15>1.2 1.25>1.2

              8、ROUND_UNNECESSARY

              斷言請求的操作具有精確的結果,因此不需要舍入。

              示例

              BigDecimal num1 = new BigDecimal("2.4");BigDecimal num2 = new BigDecimal("2");BigDecimal result1 = num2.divide(num1,3,BigDecimal.ROUND_UP);BigDecimal result2 = num2.divide(num1,3,BigDecimal.ROUND_DOWN);BigDecimal result3 = num2.divide(num1,3,BigDecimal.ROUND_CEILING);BigDecimal result4 = num2.divide(num1,3,BigDecimal.ROUND_FLOOR);BigDecimal result5 = num2.divide(num1,3,BigDecimal.ROUND_HALF_UP);BigDecimal result6 = num2.divide(num1,3,BigDecimal.ROUND_HALF_DOWN);BigDecimal result7 = num2.divide(num1,3,BigDecimal.ROUND_HALF_EVEN);System.out.println("BigDecimal.ROUND_UP result1:"+result1);System.out.println("BigDecimal.ROUND_DOWN result2:"+result2);System.out.println("BigDecimal.ROUND_CEILING result3:"+result3);System.out.println("BigDecimal.ROUND_FLOOR result4:"+result4);System.out.println("BigDecimal.ROUND_HALF_UP result5:"+result5);System.out.println("BigDecimal.ROUND_HALF_DOWN result6:"+result6);System.out.println("BigDecimal.ROUND_HALF_EVEN result7:"+result7);

              輸出結果

              BigDecimal.ROUND_UP result1:0.834BigDecimal.ROUND_DOWN result2:0.833BigDecimal.ROUND_CEILING result3:0.834BigDecimal.ROUND_FLOOR result4:0.833BigDecimal.ROUND_HALF_UP result5:0.833BigDecimal.ROUND_HALF_DOWN result6:0.833BigDecimal.ROUND_HALF_EVEN result7:0.833

              這里要注意ROUND_UNNECESSARY如果相除是無限小數會報異常

              BigDecimal num1 = new BigDecimal("2.4");BigDecimal num2 = new BigDecimal("2");BigDecimal result8 = num2.divide(num1,2,BigDecimal.ROUND_UNNECESSARY);System.out.println("BigDecimal.ROUND_UNNECESSARY result8:"+result8);

              輸出結果

              Exception in thread "main" java.lang.ArithmeticException: Rounding necessaryat java.math.BigDecimal.commonNeedIncrement(BigDecimal.java:4179)at java.math.BigDecimal.needIncrement(BigDecimal.java:4235)at java.math.BigDecimal.divideAndRound(BigDecimal.java:4143)at java.math.BigDecimal.divide(BigDecimal.java:5214)at java.math.BigDecimal.divide(BigDecimal.java:1564)at fking.Demo5.main(Demo5.java:35)

              如果改成

              BigDecimal num1 = new BigDecimal("2");BigDecimal num2 = new BigDecimal("5");BigDecimal result8 = num2.divide(num1,2,BigDecimal.ROUND_UNNECESSARY);System.out.println("BigDecimal.ROUND_UNNECESSARY result8:"+result8);

              輸出結果

              BigDecimal.ROUND_UNNECESSARY result8:2.50

              總結結論

              (1)商業計算使用BigDecimal。

              ? (2)盡量使用參數類型為String的構造函數。

              ? (3) BigDecimal都是不可變的(immutable)的,在進行每一步運算時,都會產生一個新的對象,所以在做加減乘除運算時千萬要保存操作后的值。

              如果大家對java架構相關感興趣,可以關注下面公眾號,會持續更新java基礎面試題, netty, spring boot,spring cloud等系列文章,一系列干貨隨時送達, 超神之路從此展開, BTAJ不再是夢想!

              責任編輯:

              標簽:

              相關推薦:

              精彩放送:

              新聞聚焦
              Top 中文字幕在线观看亚洲日韩