BigDecimal除法的精度問題
在使用BigDecimal的除法時,遇到一個鬼畜的問題,本以為的精度計算,結果使用傳回0,當然最終發現還是自己的使用姿勢不對導緻的,是以記錄一下,避免後面重蹈覆轍
在使用BigDecimal做高精度的除法時,一不注意遇到了一個小問題,如下
<code> </code>
<code>}</code>
上面的輸出是什麼 ?
為什麼前面兩個會是0呢,如果直接是 <code>541253 / 12389431</code> = 0 倒是可以了解, 但是BigDecimal不是高精度的計算麼,講道理不應該不會出現這種整除的問題吧
我們知道在BigDecimal做觸發時,可以指定保留小數的參數,如果加上這個,是否會不一樣呢?
<code>BigDecimal val = origin.divide(now, 5, RoundingMode.HALF_UP);</code><code>System.out.println(val);</code>
輸出結果為:
是以說在指定了保留小數之後,則沒有問題,是以大膽的猜測一下,是不是上面的幾種case中,由于scale值沒有指定時,預設值不一樣,進而導緻最終結果的精度不同呢?
簡單的深入源碼分析一下,執行的方式為 <code>origin.divide(now, RoundingMode.HALF_UP);</code>, 是以這個scale參數就瞄準origin對象,而這個對象,就隻能去分析它的構造了,因為沒有其他的地方使用
分析下面這一行, 直接進入源碼
很明顯的int傳參構造,進去簡單看一下
<code>public BigDecimal(long val) {</code><code>this.intCompact = val;</code><code>this.intVal = (val == INFLATED) ? INFLATED_BIGINT : null;</code><code>this.scale = 0;</code><code>}</code>
so,很明确的知道預設的scale為0,也就是說當origin為正數時,以它進行的除法,不現實指定scale參數時,最終傳回的都是沒有小數的,同樣看一眼,還有long的傳參方式, BigInteger也一樣
接下來就是浮點的scale預設值确認了,這個構造相比前面的複雜一點,源碼就不貼了,太長,也看不太懂做了些啥,直接用猥瑣一點的方式,進入debug模式,單步執行
依然是一大串的邏輯,同樣采用單步debug的方式試下
上面三個的scale都是1
對于BigDecimal進行除法運算時,最好指定其scale參數,不然可能會有坑
對于BigDecimla的scale初始化的原理,有待深入看下BigDecimal是怎麼實作的
最後貼一張乘法的圖作為收尾