激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

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

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

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 久久免费激情视频 | 国产精品jk白丝蜜臀av软件 | 精品无吗乱吗av国产爱色 | 久久久久久久久久久影视 | 麻豆视频在线免费观看 | 免费看黄色一级大片 | 久久99亚洲精品久久99果 | 精品一区二区久久久久久按摩 | 国产www免费 | 日韩av电影在线免费观看 | 视频一区二区三区在线播放 | 亚洲一区二区免费 | 国产jjizz一区二区三区视频 | 国产一区免费观看 | 369看片你懂的小视频在线观看 | 成人乱人乱一区二区三区 | 国产精品剧情一区二区在线观看 | 欧美成年性h版影视中文字幕 | 精品国产96亚洲一区二区三区 | 欧美日本另类 | 成人做爽爽爽爽免费国产软件 | 国产99精品在线 | 久久久久久久网站 | 噜噜色av| 亚洲美女网站在线观看 | 成人区一区二区三区 | 亚洲免费资源 | 久久亚洲精品视频 | 精品无码久久久久久国产 | 国外成人在线视频 | 一级全毛片 | 免费a级毛片大学生免费观看 | 91九色精品国产 | 久久精品视频一区 | 宅男噜噜噜66国产在线观看 | 色诱亚洲精品久久久久久 | 黑人三级毛片 | 午夜视频在线观看免费视频 | 狼人狠狠干 | 国产乱一区二区三区视频 | 午色影院 |