Java BigDecimal 精度計算 「捨入」 你用對了嗎?

2021-02-19 穀粒果

開篇,國際慣例模式 「先吹牛」,先給小白科普一下 BigDecimal。

Java在java.math包中提供的API類BigDecimal,用來對超過16位有效位的數進行精確的運算。雙精度浮點型變量double可以處理16位有效數,但在實際應用中,可能需要對更大或者更小的數進行運算和處理。一般情況下,對於那些不需要準確計算精度的數字,我們可以直接使用Float和Double處理,但是Double.valueOf(String) 和Float.valueOf(String)會丟失精度。所以開發中,如果我們需要精確計算的結果,則必須使用BigDecimal類來操作。

BigDecimal所創建的是對象,故我們不能使用傳統的+、-、*、/等算術運算符直接對其對象進行數學運算,而必須調用其相對應的方法。方法中的參數也必須是BigDecimal的對象。構造器是類的特殊方法,專門用來創建對象,特別是帶有參數的對象。

BigDecimal對象中的值相加,返回BigDecimal對象

BigDecimal對象中的值相減,返回BigDecimal對象。

BigDecimal對象中的值相乘,返回BigDecimal對象。

BigDecimal對象中的值相除,返回BigDecimal對象。

搭配 NumberFormat 類的 format() 方法可以直接將 BigDecimal 對象作為參數進行格式化處理,可以對超出16位有效數字的貨幣值、百分值、以及一般數值進行格式化控制。

這裡是本文重點要科普的點,雖然內容不多,但是較為重要!如果你做銀行、金融相關領域,則更應該掌握。

打開 BigDecimal 類,可以看到如下幾個常量
                    public final static int ROUND_UP =           0;
public final static int ROUND_DOWN = 1;
public final static int ROUND_CEILING = 2;
public final static int ROUND_FLOOR = 3;
public final static int ROUND_HALF_UP = 4;
public final static int ROUND_HALF_DOWN = 5;
public final static int ROUND_HALF_EVEN = 6;
public final static int ROUND_UNNECESSARY = 7;

所謂銀行家捨入法,其實質是一種四捨六入五取偶(又稱四捨六入五留雙)法。

System.out.println(new BigDecimal(1.15).setScale(1,BigDecimal.ROUND_HALF_EVEN).toString());

如果你告訴我輸出的是 1.2,那你就又錯了,它輸出的結果是 1.1。哈哈哈…… 

我來告訴你為什麼,代碼中 new BigDecimal(1.15) 會丟失精度,請使用 new BigDecimal("1.15")  這樣的寫法!

所以,銀行家捨入法 BigDecimal.ROUND_HALF_EVEN 應當選本文的主角,請記住它。

最後,為什麼銀行家捨入是相對很合理的呢?這個問題留給你,數據模型會告訴你答案 —— 它確實相對很合理。

相關焦點

  • 你以為BigDecimal就一定不會丟失精度了嗎,錯!
    本文轉載自【微信公眾號:java進階架構師,ID:java_jiagoushi】經微信公眾號授權轉載,如需轉載與原文作者聯繫前言我們基本已經形成了常識,需要用到金錢的地方要用BigDecimal而不是其他,而我們也都知道浮點型變量在進行計算的時候會出現丟失精度的問題。那麼,你知道其實BigDecimal也會丟失精度嗎?
  • Java 中的 BigDecimal,你真的會用嗎?
    一般情況下,對於那些不需要準確計算精度的數字,我們可以直接使用Float和Double處理,但是Double.valueOf(String) 和Float.valueOf(String)會丟失精度。所以開發中,如果我們需要精確計算的結果,則必須使用BigDecimal類來操作。
  • Java中的BigDecimal,你真的會用嗎?
    一般情況下,對於那些不需要準確計算精度的數字,我們可以直接使用Float和Double處理,但是Double.valueOf(String) 和Float.valueOf(String)會丟失精度。所以開發中,如果我們需要精確計算的結果,則必須使用BigDecimal類來操作。
  • BigDecimal如何使用?
    跟著我從0學習JAVA、spring全家桶和linux運維等知識,帶你從懵懂少年走向人生巔峰,迎娶白富美!每一篇文章都是心得總結,跟我學習你就是大牛!BigDecimal如何使用?1 BigDecimal簡述      BigDecimal類是java.math包提供的用於準確計算的API類,用來對超過16位有效位的數進行精確的運算。
  • Java中的數學運算BigDecimal
    返回大於目標數的最小整數        System.out.println("Math.ceil(1.2):"+Math.ceil(1.2)); // 2.0        // 四捨五入取整        System.out.println("Math.round(2.3):" +Math.round(2.3)); // 2        /* 大小相關計算
  • 從java中來說:2減1.1等於幾?
    所以這裡得出經驗,在實際開發中,我們在對數值進行計算的時候,應儘量避免使用Java的+ - * / 等運算符,因為容易出現損失精度的問題,導致最終的計算結果錯誤。尤其是在電商平臺中都是杜絕使用此種計算方式的,因為由於這種計算導致金額出現的誤差,所帶來的損失是無法估量的,也許就因為差一分錢,導致報表計算錯誤,客戶帳單對不上,都會帶來大麻煩。
  • 浮點精度(二)
    原理分析浮點數在計算機中的存儲採用 IEEE 754標準,數據塊分為符號位、指數位、尾數位,單精度和雙精度各部分位數長度如下:當一個浮點數不能被精確存儲時,需要進行捨入操作,IEEE標準中列舉出了幾種:捨入到最接近:捨入到最接近,在一樣接近的情況下偶數優先,即在二進位中式以0結尾的,
  • 面試官:BigDecimal一定不會丟失精度嗎?
    而不是其他,而我們也都知道浮點型變量在進行計算的時候會出現丟失精度的問題。那麼,你知道其實BigDecimal也會丟失精度嗎?而使用BigDecimal的背後又有什麼值得去探究的地方嗎?今天,告訴你,知其然,也知其所以然。
  • Excel中捨入與取整計算的基本教程
    二、使用INT函數返回永遠小於原數字的最接近的整數INT函數可以依照給定數的小數部分的值,將其向下捨入到最接近的整數。如使用INT函數返回8.965的整數部分,輸入【=INT(8.965)】即可,返回【8】。
  • java float double精度為什麼會丟失?淺談java的浮點數精度問題
    於是帶著這個問 題,做了一次關於float和double學習,做個簡單分享,希望有助於大家對java 浮 點數的理解。 關於 java 的 float 和 doubleJava 語言支持兩種基本的浮點類型: float 和 double 。
  • 淺析浮點數精度問題
    很多開發人員因浮點數難以掌控的精度問題而儘量避免使用浮點數。本文從浮點數的表示方法入手,淺析浮點數的精度問題,希望可以加深大家對浮點數的理解。常用的浮點數有單精度浮點數(float)和雙精度浮點數(double),本文主要以單精度浮點數為例,雙精度浮點數原理相同。通常使用IEEE754標準存儲和表示浮點數。IEEE754標準用以下形式來表示一個浮點數。
  • 注意了,這些數值計算的坑千萬別踩!
    避免用 Double 來運算  我們以為的算術運算和計算機計算的並不完全一致。  這是因為計算機是以二進位存儲數值的,我們輸入的十進位數值都會轉換成二進位進行計算,十進位轉二進位再轉換成十進位就不是原來那個十進位了 。
  • HR,這些EXCEL捨入函數你必須要了解
    今天帶給大家一大波捨入函數,在你的工作中總會用到的,趕緊收藏哦。用法:TRUNC(數值,指定取整精度),第二個參數可省略INT和TRUNC 僅當作用於負數時才有所不同:TRUNC(-4.3)返回-4而INT(-4.3) 返回-5,因為-5是更小的數字。
  • 新手注意:Java中使用BigDecimal類時要避免的坑
    Java中使用BigDecimal類時要避免的坑除了NG行,其他行的輸出結果依次為:43.343.333.343.333.333.332.50總結:果兩數相除,除不盡時,需要指定保留精度和進位方式java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.2、對象比較時含精度比較問題直接看例子02:
  • Excel向上或向下倍數捨入函數ceiling和floor介紹
    >如果你在統計數據需求時,原數據為57,你希望這個數據變成12的倍數的最小值,那麼你就會用至倍數捨入函數了向上捨入:CEILING(number,significance)向下捨入:FLOOR(number,significance)number:需要捨入的數值significance:按多少倍數
  • Excel中的捨入問題,做會計的不可以不懂!
    在B2單元格中輸入以下公式:ROUND函數是最常用的一個四捨五入的函數,一般情況下用得最多的是保留兩位小數。該函數的 語法一般為:如下圖所示,對下面的數字四捨五入後保留一位小數。在B2單元格中輸入以下公式:ROUNDUP函數是四捨五入的另外一種捨入方式。主要用於對一個數字向上捨入。該函數的一般語法可以寫成:如下圖所示 ,將數字向上捨入並保留一位小數。
  • Excel中的捨入,做財務的怎麼可以不知道!
    ROUND函數是最常用的一個四捨五入的函數,一般情況下用得最多的是保留兩位小數。       FLOOR函數是一個不是十地常用的函數,但是這個函數十分地有用。一般常用的語法為:FLOOR(數字,指定的基數)如圖所示 ,將下面的數字如果小數部分大於0.5時按0.5計算,小於0.5時按0計算。
  • Excel中的捨入,做財務的怎麼可以不知道
    在B2單元格中輸入以下公式:  ROUND函數是最常用的一個四捨五入的函數,一般情況下用得最多的是保留兩位小數。該函數的 語法一般為:第二個參數為可選參數,默認情況下為0.在B2單元格中輸入以下公式:  FLOOR函數是一個不是十地常用的函數,但是這個函數十分地有用。該函數的功能是將一個數字按照指定的基數的倍數向下捨入。
  • WPS表格數值捨入函數大閱兵!
    【IT168 論壇採風】在數值計算過程中,經常要遇到對結果進行捨入的情況,WPS表格提供了豐富的捨入函數,下面我們就對這些函數進行一次大閱兵:相關精彩文章
  • Java和Python中的整數除法,取餘,捨入
    關於除法,你也許覺得沒什麼值得談論的