在使用BigDecimal的除法時,遇到一個鬼畜的問題,本覺得的精度計算,結果使用返回0,固然最終發現仍是本身的使用姿式不對致使的,所以記錄一下,避免後面重蹈覆轍java
<!-- more -->git
在使用BigDecimal作高精度的除法時,一不注意遇到了一個小問題,以下github
@Test public void testBigDecimal() { BigDecimal origin = new BigDecimal(541253); BigDecimal now = new BigDecimal(12389431); BigDecimal val = origin.divide(now, RoundingMode.HALF_UP); System.out.println(val); origin = new BigDecimal(541253); now = new BigDecimal(12389431.3); val = origin.divide(now, RoundingMode.HALF_UP); System.out.println(val); origin = new BigDecimal(541253.4); now = new BigDecimal(12389431); val = origin.divide(now, RoundingMode.HALF_UP); System.out.println(val); }
上面的輸出是什麼 ?ide
0 0 0.043686703610520937021487456961257
爲何前面兩個會是0呢,若是直接是 541253 / 12389431
= 0 卻是能夠理解, 可是BigDecimal不是高精度的計算麼,講道理不該該不會出現這種整除的問題吧源碼分析
咱們知道在BigDecimal作觸發時,能夠指定保留小數的參數,若是加上這個,是否會不同呢?學習
BigDecimal origin = new BigDecimal(541253); BigDecimal now = new BigDecimal(12389431); BigDecimal val = origin.divide(now, 5, RoundingMode.HALF_UP); System.out.println(val);
輸出結果爲:this
0.04369
因此說在指定了保留小數以後,則沒有問題,因此大膽的猜想一下,是否是上面的幾種case中,因爲scale值沒有指定時,默認值不同,從而致使最終結果的精度不一樣呢?debug
簡單的深刻源碼分析一下,執行的方式爲 origin.divide(now, RoundingMode.HALF_UP);
, 因此這個scale參數就瞄準origin對象,而這個對象,就只能去分析它的構造了,由於沒有其餘的地方使用code
分析下面這一行, 直接進入源碼對象
BigDecimal origin = new BigDecimal(541253);
很明顯的int傳參構造,進去簡單看一下
// java.math.BigDecimal#BigDecimal(int) public BigDecimal(int val) { this.intCompact = val; this.scale = 0; this.intVal = null; } public BigDecimal(long val) { this.intCompact = val; this.intVal = (val == INFLATED) ? INFLATED_BIGINT : null; this.scale = 0; }
so,很明確的知道默認的scale爲0,也就是說當origin爲正數時,以它進行的除法,不現實指定scale參數時,最終返回的都是沒有小數的,一樣看一眼,還有long的傳參方式, BigInteger也同樣
接下來就是浮點的scale默認值確認了,這個構造相比前面的複雜一點,源碼就不貼了,太長,也看不太懂作了些啥,直接用猥瑣一點的方式,進入debug模式,單步執行
@Test public void testBigDecimal() { BigDecimal origin = new BigDecimal(541253.0); BigDecimal now = new BigDecimal(12389431.1); BigDecimal tmp = new BigDecimal(0.0); }
根據debug的結果,第一個,scale爲0; 第二個scale爲29, 第三個scale爲0
依然是一大串的邏輯,一樣採用單步debug的方式試下
@Test public void testBigDecimal() { BigDecimal origin = new BigDecimal("541253.0"); BigDecimal now = new BigDecimal("12389431.1"); BigDecimal t = new BigDecimal("0.0"); }
上面三個的scale都是1
最後貼一張乘法的圖做爲收尾
一灰灰的我的博客,記錄全部學習和工做中的博文,歡迎你們前去逛逛
盡信書則不如,已上內容,純屬一家之言,因我的能力有限,不免有疏漏和錯誤之處,如發現bug或者有更好的建議,歡迎批評指正,不吝感激