成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專(zhuān)欄INFORMATION COLUMN

180706-BigDecimal除法的精度問(wèn)題

imccl / 1557人閱讀

摘要:除法的精度問(wèn)題在使用的除法時(shí),遇到一個(gè)鬼畜的問(wèn)題,本以為的精度計(jì)算,結(jié)果使用返回,當(dāng)然最終發(fā)現(xiàn)還是自己的使用姿勢(shì)不對(duì)導(dǎo)致的,因此記錄一下,避免后面重蹈覆轍問(wèn)題拋出在使用做高精度的除法時(shí),一不注意遇到了一個(gè)小問(wèn)題,如下上面的輸出是什么

BigDecimal除法的精度問(wèn)題

在使用BigDecimal的除法時(shí),遇到一個(gè)鬼畜的問(wèn)題,本以為的精度計(jì)算,結(jié)果使用返回0,當(dāng)然最終發(fā)現(xiàn)還是自己的使用姿勢(shì)不對(duì)導(dǎo)致的,因此記錄一下,避免后面重蹈覆轍

I. 問(wèn)題拋出

在使用BigDecimal做高精度的除法時(shí),一不注意遇到了一個(gè)小問(wèn)題,如下

@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

為什么前面兩個(gè)會(huì)是0呢,如果直接是 541253 / 12389431 = 0 倒是可以理解, 但是BigDecimal不是高精度的計(jì)算么,講道理不應(yīng)該不會(huì)出現(xiàn)這種整除的問(wèn)題吧

我們知道在BigDecimal做觸發(fā)時(shí),可以指定保留小數(shù)的參數(shù),如果加上這個(gè),是否會(huì)不一樣呢?

BigDecimal origin = new BigDecimal(541253);
BigDecimal now = new BigDecimal(12389431);

BigDecimal val = origin.divide(now, 5, RoundingMode.HALF_UP);
System.out.println(val);

輸出結(jié)果為:

0.04369

所以說(shuō)在指定了保留小數(shù)之后,則沒(méi)有問(wèn)題,所以大膽的猜測(cè)一下,是不是上面的幾種case中,由于scale值沒(méi)有指定時(shí),默認(rèn)值不一樣,從而導(dǎo)致最終結(jié)果的精度不同呢?

簡(jiǎn)單的深入源碼分析一下,執(zhí)行的方式為 origin.divide(now, RoundingMode.HALF_UP);, 所以這個(gè)scale參數(shù)就瞄準(zhǔn)origin對(duì)象,而這個(gè)對(duì)象,就只能去分析它的構(gòu)造了,因?yàn)闆](méi)有其他的地方使用

II. 源碼定位 1. 整形傳參構(gòu)造

分析下面這一行, 直接進(jìn)入源碼

BigDecimal origin = new BigDecimal(541253);

很明顯的int傳參構(gòu)造,進(jìn)去簡(jiǎn)單看一下

// 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,很明確的知道默認(rèn)的scale為0,也就是說(shuō)當(dāng)origin為正數(shù)時(shí),以它進(jìn)行的除法,不現(xiàn)實(shí)指定scale參數(shù)時(shí),最終返回的都是沒(méi)有小數(shù)的,同樣看一眼,還有l(wèi)ong的傳參方式, BigInteger也一樣

2. 浮點(diǎn)傳參

接下來(lái)就是浮點(diǎn)的scale默認(rèn)值確認(rèn)了,這個(gè)構(gòu)造相比前面的復(fù)雜一點(diǎn),源碼就不貼了,太長(zhǎng),也看不太懂做了些啥,直接用猥瑣一點(diǎn)的方式,進(jìn)入debug模式,單步執(zhí)行

@Test
public void testBigDecimal() {
    BigDecimal origin = new BigDecimal(541253.0);
    BigDecimal now = new BigDecimal(12389431.1);
    BigDecimal tmp = new BigDecimal(0.0);
}

根據(jù)debug的結(jié)果,第一個(gè),scale為0; 第二個(gè)scale為29, 第三個(gè)scale為0

3. String傳參

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

@Test
public void testBigDecimal() {
    BigDecimal origin = new BigDecimal("541253.0");
    BigDecimal now = new BigDecimal("12389431.1");
    BigDecimal t = new BigDecimal("0.0");
}

上面三個(gè)的scale都是1

4. 小結(jié)

對(duì)于BigDecimal進(jìn)行除法運(yùn)算時(shí),最好指定其scale參數(shù),不然可能會(huì)有坑

對(duì)于BigDecimla的scale初始化的原理,有待深入看下BigDecimal是怎么實(shí)現(xiàn)的

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

II. 其他 1. 一灰灰Blog: https://liuyueyi.github.io/he...

一灰灰的個(gè)人博客,記錄所有學(xué)習(xí)和工作中的博文,歡迎大家前去逛逛

2. 聲明

盡信書(shū)則不如,已上內(nèi)容,純屬一家之言,因個(gè)人能力有限,難免有疏漏和錯(cuò)誤之處,如發(fā)現(xiàn)bug或者有更好的建議,歡迎批評(píng)指正,不吝感激

微博地址: 小灰灰Blog

QQ: 一灰灰/3302797840

3. 掃描關(guān)注

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/71492.html

相關(guān)文章

  • 關(guān)于 JavaScript 浮點(diǎn)運(yùn)算精度解決方案

    摘要:原因至于問(wèn)題產(chǎn)生的原因,或者關(guān)于問(wèn)題的更詳細(xì)的描述,大家請(qǐng)看下面幾個(gè)文章浮點(diǎn)運(yùn)算浮點(diǎn)值運(yùn)算舍入誤差基礎(chǔ)浮點(diǎn)數(shù)四則運(yùn)算精度丟失問(wèn)題解決方案這里主要討論一下解決方案的問(wèn)題,上面幾篇文章的解決思路,都是重寫(xiě)加法減法乘法和除法運(yùn)算。 問(wèn)題背景 在 chrome 瀏覽器中調(diào)出開(kāi)發(fā)者工具,在控制臺(tái)窗口輸入下面的表達(dá)式: 0.1 + 0.2 // 期望:0.3,結(jié)果:0.300...

    jsyzchen 評(píng)論0 收藏0
  • 精度數(shù)學(xué)運(yùn)算

    摘要:使用,保證精度的同時(shí),能精準(zhǔn)的進(jìn)行四舍六入計(jì)算。類(lèi)精確的數(shù)學(xué)運(yùn)算使用來(lái)實(shí)現(xiàn)精準(zhǔn)度因?yàn)榫鹊脑驑?gòu)造方法的結(jié)果有一定的不可預(yù)知性,例如因此建議使用。算法規(guī)則四舍六入五考慮,五后非零就進(jìn)一,五后皆零看奇偶,五前為偶應(yīng)舍去,五前為奇要進(jìn)一。 四舍六入計(jì)算 算法規(guī)則: 四舍六入五考慮, 五后非零就進(jìn)一, 五后皆零看奇偶, 五前為偶應(yīng)舍去, 五前為奇要進(jìn)一。 使用BigDecimal,保證精度的...

    liaosilzu2007 評(píng)論0 收藏0
  • 數(shù)據(jù)精度問(wèn)題自查手冊(cè)

    摘要:前言在數(shù)據(jù)敏感的業(yè)務(wù)場(chǎng)景中,常常會(huì)碰到數(shù)據(jù)精度問(wèn)題,尤其在金額顯示占比統(tǒng)計(jì)等地方,該問(wèn)題尤為顯著。計(jì)算機(jī)原理真香數(shù)值的精度問(wèn)題,其實(shí)是非?;A(chǔ)的計(jì)算機(jī)原理知識(shí)。前言 在數(shù)據(jù)敏感的業(yè)務(wù)場(chǎng)景中,常常會(huì)碰到數(shù)據(jù)精度問(wèn)題,尤其在金額顯示、占比統(tǒng)計(jì)等地方,該問(wèn)題尤為顯著。由于數(shù)據(jù)的每一位有效數(shù)字都包含真實(shí)的業(yè)務(wù)語(yǔ)義,一點(diǎn)點(diǎn)偏差甚至可能影響業(yè)務(wù)決策,這讓問(wèn)題的嚴(yán)重性上升了幾個(gè)階梯。 那,什么是精度丟失...

    liangzai_cool 評(píng)論0 收藏0
  • PHP處理數(shù)學(xué)精度

    摘要:后來(lái)我看了下,確實(shí)有這么一個(gè)擴(kuò)展庫(kù),處理任意精度數(shù)字,對(duì)于任意精度的數(shù)學(xué),提供了支持用字符串表示的任意大小和精度的數(shù)字的二進(jìn)制計(jì)算。 用編程語(yǔ)言做計(jì)算,很多時(shí)候浮點(diǎn)數(shù)精度都是困擾過(guò)我的問(wèn)題,即便是剛學(xué)PHP的新手也會(huì)在群里問(wèn)為什么我的計(jì)算結(jié)果明顯不對(duì),而我們總是老態(tài)龍鐘的丟出一句浮點(diǎn)數(shù)計(jì)算都存在精度問(wèn)題,并沒(méi)有提出過(guò)什么實(shí)質(zhì)性的改善。比如下面的計(jì)算 0.57*100: zhgxun-p...

    chaos_G 評(píng)論0 收藏0
  • Java各種數(shù)據(jù)類(lèi)型,自己學(xué)習(xí)寫(xiě)筆記?。?!

    摘要:局部變量聲明在函數(shù)內(nèi)部的變量。在作用域范圍內(nèi)不能出現(xiàn)命名沖突。 java編程規(guī)范: 1.良好的標(biāo)識(shí)符的命名 保留字不能作為標(biāo)識(shí)符命名: class、public、static..., goto,const 區(qū)分大小寫(xiě):helloWorld、HelloWorld 2.良好的注釋習(xí)慣 3.良好的縮進(jìn):沒(méi)遇到一個(gè)代碼塊縮進(jìn)一次(一個(gè)tab鍵) 變量:代...

    stefanieliang 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<