天天看點

Java大數類BigDecimal及八種舍入模式的介紹

BigDecimal的引入

在利用Java程式設計語言開發銀行、金融類等需要對數值進行高精度計算的軟體時,我們經常使用​<code>​BigDecimal​</code>​和​<code>​BigInteger​</code>​這兩個大資料類,而不是常見的int、long、float、double類型,特别是在處理浮點型資料。

我們先看一下使用基礎資料類型double進行計算并列印結果的一個代碼示範:

結果如下:

問題來了,為什麼會出現第二種結果的資料呢?根本原因還是我們的計算機是由二進制的,而二進制是沒辦法來精确表示一個浮點數,CPU采用“尾數和指數”的方式(科學計數法)表達浮點數的時候存在一定的誤差。是以,當對資料精度要求比較高的時候,還是需要采用BigDecimal類,盡管計算速度上稍微慢了一些。

BigDecimal的使用

建立一個BigDecimal對象有構造函數和公有靜态方法(BigDecimal.valueOf)兩種方式,需要注意兩點:

構造函數包含使用基本資料類型和字元串作為參數的兩種形式,推薦使用後者,如:<code>new BigDecimal(Double.valueOf(0.09))</code>。大家可以嘗試一下,<code>System.out.println(new BigDecimal(0.06).toString());</code>語句的輸出結果是:0.059999999999999997779553950749686919152736663818359375

Decimal列印日志或向基本資料類型轉換時,盡量使用它提供的公有方法xxxValue(),比如doubleValue(),而不是簡單粗暴的一個toString()。

BigDecimal舍入模式

盡管資料庫存儲的是一個高精度的浮點數,但是通常在應用中展示的時候往往需要限制一下小數點的位數,比如兩到三位小數即可,這時就需要使用到​<code>​setScale(int newScale, int roundingMode)​</code>​函數,作為BigDecimal的公有靜态變量,舍入模式(Rounding Mode)的運算規則比較多,公有八種,這裡作個說明,官方文檔也有介紹。

ROUND_UP

向遠離零的方向舍入。舍棄非零部分,并将非零舍棄部分相鄰的一位數字加一。

ROUND_DOWN

向接近零的方向舍入。舍棄非零部分,同時不會非零舍棄部分相鄰的一位數字加一,采取截取行為。

ROUND_CEILING

向正無窮的方向舍入。如果為正數,舍入結果同ROUND_UP一緻;如果為負數,舍入結果同ROUND_DOWN一緻。注意:此模式不會減少數值大小。

ROUND_FLOOR

向負無窮的方向舍入。如果為正數,舍入結果同ROUND_DOWN一緻;如果為負數,舍入結果同ROUND_UP一緻。注意:此模式不會增加數值大小。

ROUND_HALF_UP

向“最接近”的數字舍入,如果與兩個相鄰數字的距離相等,則為向上舍入的舍入模式。如果舍棄部分&gt;= 0.5,則舍入行為與ROUND_UP相同;否則舍入行為與ROUND_DOWN相同。這種模式也就是我們常說的我們的“四舍五入”。

ROUND_HALF_DOWN

向“最接近”的數字舍入,如果與兩個相鄰數字的距離相等,則為向下舍入的舍入模式。如果舍棄部分&gt; 0.5,則舍入行為與ROUND_UP相同;否則舍入行為與ROUND_DOWN相同。這種模式也就是我們常說的我們的“五舍六入”。

ROUND_HALF_EVEN

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

ROUND_UNNECESSARY

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

下面,舉個例子說明一下不同舍入模式下的數值計算結果,保留一位小數:

<col>

INPUT_NUM

UP

DOWN

CEILING

FLOOR

HALF_UP

HALF_DOWN

HALF_EVEN

UNNECESSARY

5.5

6

5

Exception

2.5

3

2

1.6

1

1.1

-1.0

-1.1

-2

-1.6

-2.5

-3

-5.5

-6

-5