一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - Java中BigDecimal除法使用不當導致精度問題

Java中BigDecimal除法使用不當導致精度問題

2022-03-09 00:56一灰灰 Java教程

本文主要介紹了Java中BigDecimal除法使用不當導致精度問題,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下

在使用BigDecimal的除法時,遇到一個鬼畜的問題,本以為的精度計算,結果使用返回0,當然最終發現還是使用姿勢不對導致的,因此記錄一下,避免后面重蹈覆轍

I. 問題拋出

在使用BigDecimal做高精度的除法時,一不注意遇到了一個小問題,如下

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@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);
}

上面的輸出是什么 ?
0
0
0.043686703610520937021487456961257

為什么前面兩個會是0呢,如果直接是 541253 / 12389431 = 0 倒是可以理解, 但是BigDecimal不是高精度的計算么,講道理不應該不會出現這種整除的問題吧

我們知道在BigDecimal做觸發時,可以指定保留小數的參數,如果加上這個,是否會不一樣呢?

?
1
2
3
4
5
BigDecimal origin = new BigDecimal(541253);
BigDecimal now = new BigDecimal(12389431);
 
BigDecimal val = origin.divide(now, 5, RoundingMode.HALF_UP);
System.out.println(val);

輸出結果為:
0.04369

所以說在指定了保留小數之后,則沒有問題,所以大膽的猜測一下,是不是上面的幾種case中,由于scale值沒有指定時,默認值不一樣,從而導致最終結果的精度不同呢?

簡單的深入源碼分析一下,執行的方式為 origin.divide(now, RoundingMode.HALF_UP);, 所以這個scale參數就瞄準origin對象,而這個對象,就只能去分析它的構造了,因為沒有其他的地方使用

II. 源碼定位

1. 整形傳參構造

分析下面這一行, 直接進入源碼

?
1
BigDecimal origin = new BigDecimal(541253);

很明顯的int傳參構造,進去簡單看一下

?
1
2
3
4
5
6
7
8
9
10
11
12
// 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也一樣

2. 浮點傳參

接下來就是浮點的scale默認值確認了,這個構造相比前面的復雜一點,源碼就不貼了,太長,也看不太懂做了些啥,直接用猥瑣一點的方式,進入debug模式,單步執行

?
1
2
3
4
5
6
@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

Java中BigDecimal除法使用不當導致精度問題

Java中BigDecimal除法使用不當導致精度問題

Java中BigDecimal除法使用不當導致精度問題

3. String傳參

依然是一大串的邏輯,同樣采用單步debug的方式試下

?
1
2
3
4
5
6
@Test
public void testBigDecimal() {
    BigDecimal origin = new BigDecimal("541253.0");
    BigDecimal now = new BigDecimal("12389431.1");
    BigDecimal t = new BigDecimal("0.0");
}

上面三個的scale都是1

4. 小結

對于BigDecimal進行除法運算時,最好指定其scale參數,不然可能會有坑
對于BigDecimla的scale初始化的原理,有待深入看下BigDecimal是怎么實現的

最后貼一張乘法的圖作為收尾

Java中BigDecimal除法使用不當導致精度問題

到此這篇關于Java中BigDecimal除法使用不當導致精度問題的文章就介紹到這了,更多相關Java BigDecimal除法精度內容請搜索服務器之家以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持服務器之家!

原文鏈接:https://juejin.cn/post/7025607161883394079

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 美女脱了内裤打开腿让人桶网站o | 亚洲日本在线观看网址 | 国产成人亚洲综合91精品555 | 草莓永久地域网名入2022 | 波多野结在线 | 18未年禁止免费观看 | 猛男壮男受bl爽哭了高h | 乌克兰xxxxx| 午夜国产精品影院在线观看 | 教室眠催白丝美女校花 | 欧美精品国产第一区二区 | 无遮免费网站在线入口 | 69av美女| 欧美人禽杂交av片 | 亚洲 欧美 国产 在线 日韩 | 久久精品国产欧美日韩99热 | 91国内精品久久久久影院优播 | 超h 超重口 高h 污肉1v1 | 男人的天堂久久精品激情 | 精品日韩二区三区精品视频 | 日本ww视频 | 2022av小四郎的最新地址 | 国产麻豆剧果冻传媒观看免费视频 | 91青青视频| 日韩高清无砖砖区2022 | 乌克兰精品摘花处破 | 国产精品密播放国产免费看 | 免费看3d小舞被躁视频网站 | 99热成人精品免费久久 | 69人成网站色www | 国产3p绿奴在线视频 | 免费午夜影院 | 国产视频一区在线观看 | 美女18隐私羞羞视频网站 | 久久亚洲午夜牛牛影视 | 国产精品一级香蕉一区 | www.99精品视频在线播放 | 国产精品久久久久久影院 | 欧美日韩中文字幕一区二区高清 | 91久久青青青国产免费 | 四虎国产精品视频免费看 |