Java-BigDecimal 分析

來源:互聯網
上載者:User

標籤:

引言

  最近在看項目中的各種計算,因為是金融方面的項目,涉及到日化,年化,利息,債轉這些和錢有關的計算很多,其中全部通過BigDecimal類進行的運算,以前涉及到的計算基本都用+、-、*、/等算術運算子直接進行數學運算,資料類型一般用double就能解決問題,但是如果要求完全精度時double就不合適了,因為double是在廣域數值範圍上提供較為精確的快速近似計算(只能處理16位有效數)。

  BigDecimal是Java在java.math包中提供的API類,主要用來對超過16位有效位的數進行精確的運算。雙精確度浮點型變數double可以處理16位有效數。在實際應用中,需要對更大或者更小的數進行運算和處理。float和double只能用來做科學計算或者是工程計算,在商業計算中要用java.math.BigDecimal。

  BigDecimal所建立的是對象,我們不能使用傳統的+、-、*、/等算術運算子直接對其對象進行數學運算,而必須調用其相對應的方法。方法中的參數也必須是BigDecimal的對象。下面來看BigDecimal的構造方法。

 

構造方法

  BigDecimal(int)建立一個具有參數所指定整數值的對象。

  BigDecimal(double)建立一個具有參數所指定雙精確度值的對象。

  BigDecimal(long)建立一個具有參數所指定長整數值的對象。

  BigDecimal(String)建立一個具有參數所指定以字串表示的數值的對象。

 

 這裡需要注意的是double類型的,先看一個執行個體:

<pre name="code" class="java">//1、BigDecimal(double)BigDecimal aDouble =new BigDecimal(1.1);System.out.println("to double: " + aDouble); // 2、BigDecimal(String)BigDecimal aString = new BigDecimal("1.1");System.out.println("to string: " + aString);//3、BigDecimal.valueOf(double)BigDecimal aValue = BigDecimal.valueOf(1.1);System.out.println("valueOf: " + aValue);


 輸出結果:

to double: 1.100000000000000088817841970012523233890533447265625to string: 1.1valueOf: 1.1
 

 1、這裡我們注意到參數為double類型是,構造的BigDecimal值實際上等於1.100000000000000088817841970012523233890533447265625,而不是1.1,這是因為1.1無法準確地表示為double(或者說對於該情況,不能表示為任何有限長度的二進位小數)。

 2、參數為String類型構造的BigDecimal值正好等於原值1.1。因此,在我們構造BigDecimal值時通常選擇參數為String類型的構造方法。

 3、當double 必須用作BigDecimal的參數時,可以先使用Double.toString(double)方法將double轉換為String,然後使用BigDecimal(String)構造方法。再使用BigDecimal.valueOf(double)方法擷取值。

 

運算方式

  加減乘除最基本的運算

  BigDecimal add(BigDecimal augend) 加法運算

  BigDecimal subtract(BigDecimal subtrahend) 減法運算

  BigDecimal multiply(BigDecimal multiplicand) 乘法運算

  BigDecimal divide(BigDecimal divisor) 除法運算


  因為追求高精度,我們使用BigDecimal,但是在進行帶除法的運算時,並且結果需要保留有效位元的時,可能會出現精度問題。那什麼時候會出現呢?

  我們知道10除3是永遠除不盡的,並且結果我們需要進行格式化(保留有效位元)

 

精度和保留模式

  BigDecimal對象的精度沒有限制。對於除不盡的除法運算,比如10/3,divide方法將會拋出 java.lang.ArithmeticException錯誤,所以除法運算要盡量使用divide(BigDecimal d, int scale, int roundMode)指定標度和保留模式來避免異常。

scale,標度,小數點保留的位元

roundMode,保留模式

BigDecimal.ROUND_DOWN:直接丟掉標度以外的小數

BigDecimal.ROUND_UP:不管捨棄的小數是幾,都進1

BigDecimal.ROUND_HALF_UP:最常見的四捨五入

還有其他的模式,可以直接去源碼裡看。


來看執行個體計算:

<pre name="code" class="java">BigDecimal a =new BigDecimal("10");BigDecimal c = a.divide(new BigDecimal(3),10,BigDecimal.ROUND_DOWN);BigDecimal d = c.multiply(new BigDecimal(3));System.out.println("value: " + c);System.out.println("value: " + d);

輸出結果為:

value: 3.3333333333
value: 9.9999999999

因為第一步的除法指定了標度和保留模式,我們得到的是一個近似值,已經丟失了精度,在進行後續的運算中,精度已經無法保證,如何解決這種問題?應該把除法運算放在整個運算的最後,以減小除法帶來的精度問題。


總結

  商業計算對錢最敏感,一分一毫平時看來很小,但是放在million,billion中,everyhundred損失a cent,結果也是巨大的。學習亦是如此,每天學習一分,一年後獲得的改變也是巨大的。




Java-BigDecimal 分析

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.