欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

淺析Java?BigDecimal為什么可以不丟失精度

 更新時間:2024年03月22日 14:31:55   作者:CaryDai  
在金融領(lǐng)域,為了保證數(shù)據(jù)的精度,往往會使用BigDecimal,所以這篇文章主要來和大家探討下為什么BigDecimal可以保證精度不丟失,感興趣的可以了解下

在金融領(lǐng)域,為了保證數(shù)據(jù)的精度,往往會使用BigDecimal。本文就來探討下為什么BigDecimal可以保證精度不丟失。

類介紹

首先來看一下BigDecimal的類聲明以及幾個屬性:

public class BigDecimal extends Number implements Comparable<BigDecimal> {
    // 該BigDecimal的未縮放值
    private final BigInteger intVal;
    // 精度,可以理解成小數(shù)點后的位數(shù)
    private final int scale;
    // BigDecimal中的十進制位數(shù),如果位數(shù)未知,則為0(備用信息)
    private transient int precision;
    // Used to store the canonical string representation, if computed.
    // 這個我理解就是存實際的BigDecimal值
    private transient String stringCache;
    // 擴大成long型數(shù)值后的值
    private final transient long intCompact;
}

從例子入手

通過debug來發(fā)現(xiàn)源碼中的奧秘是了解類運行機制很好的方式。 請看下面的testBigDecimal方法:

@Test
public void testBigDecimal() {
    BigDecimal bigDecimal1 = BigDecimal.valueOf(2.36);
    BigDecimal bigDecimal2 = BigDecimal.valueOf(3.5);
    BigDecimal resDecimal = bigDecimal1.add(bigDecimal2);
    System.out.println(resDecimal);
}

在執(zhí)行了BigDecimal.valueOf(2.36)后,查看debug信息可以發(fā)現(xiàn)上述提到的幾個屬性被賦了值:

接下來進到add方法里面,看看它是怎么計算的:

/**
 * Returns a BigDecimal whose value is (this + augend), 
 * and whose scale is max(this.scale(), augend.scale()).
 */
public BigDecimal add(BigDecimal augend) {
    if (this.intCompact != INFLATED) {
        if ((augend.intCompact != INFLATED)) {
            return add(this.intCompact, this.scale, augend.intCompact, augend.scale);
        } else {
            return add(this.intCompact, this.scale, augend.intVal, augend.scale);
        }
    } else {
        if ((augend.intCompact != INFLATED)) {
            return add(augend.intCompact, augend.scale, this.intVal, this.scale);
        } else {
            return add(this.intVal, this.scale, augend.intVal, augend.scale);
        }
    }
}

看一下傳進來的值:

進入第8行的add方法:

private static BigDecimal add(final long xs, int scale1, final long ys, int scale2) {
    long sdiff = (long) scale1 - scale2;
    if (sdiff == 0) {
        return add(xs, ys, scale1);
    } else if (sdiff < 0) {
        int raise = checkScale(xs,-sdiff);
        long scaledX = longMultiplyPowerTen(xs, raise);
        if (scaledX != INFLATED) {
            return add(scaledX, ys, scale2);
        } else {
            BigInteger bigsum = bigMultiplyPowerTen(xs,raise).add(ys);
            return ((xs^ys)>=0) ? // same sign test
                new BigDecimal(bigsum, INFLATED, scale2, 0)
                : valueOf(bigsum, scale2, 0);
        }
    } else {
        int raise = checkScale(ys,sdiff);
        long scaledY = longMultiplyPowerTen(ys, raise);
        if (scaledY != INFLATED) {
            return add(xs, scaledY, scale1);
        } else {
            BigInteger bigsum = bigMultiplyPowerTen(ys,raise).add(xs);
            return ((xs^ys)>=0) ?
                new BigDecimal(bigsum, INFLATED, scale1, 0)
                : valueOf(bigsum, scale1, 0);
        }
    }
}

這個例子中,該方法傳入的參數(shù)分別是:xs=236,scale1=2,ys=35,scale2=1 該方法首先計算scale1 - scale2,根據(jù)差值走不同的計算邏輯,這里求出來是1,所以進入到最下面的else代碼塊(這塊是關(guān)鍵):

  • 首先17行校驗了一下數(shù)值范圍
  • 18行將ys擴大了10的n次倍,這里n=raise=1,所以返回的scaledY=350
  • 接著就進入到20行的add方法:
private static BigDecimal add(long xs, long ys, int scale){
    long sum = add(xs, ys);
    if (sum!=INFLATED)
        return BigDecimal.valueOf(sum, scale);
    return new BigDecimal(BigInteger.valueOf(xs).add(ys), scale);
}

這個方法很簡單,就是計算和,然后返回BigDecimal對象:

結(jié)論

所以可以得出結(jié)論:BigDecimal在計算時,實際會把數(shù)值擴大10的n次倍,變成一個long型整數(shù)進行計算,整數(shù)計算時自然可以實現(xiàn)精度不丟失。同時結(jié)合精度scale,實現(xiàn)最終結(jié)果的計算。

到此這篇關(guān)于淺析Java BigDecimal為什么可以不丟失精度的文章就介紹到這了,更多相關(guān)Java BigDecimal精度丟失內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java調(diào)用setStroke()方法設(shè)置筆畫屬性的語法

    Java調(diào)用setStroke()方法設(shè)置筆畫屬性的語法

    這篇文章主要介紹了Java調(diào)用setStroke()方法設(shè)置筆畫屬性的語法,如何改變線條的粗細(xì)、虛實和定義線段端點的形狀、風(fēng)格等,需要的朋友可以參考下
    2017-09-09
  • Java字符串去除特殊字符內(nèi)容的實例

    Java字符串去除特殊字符內(nèi)容的實例

    下面小編就為大家分享一篇Java字符串去除特殊字符內(nèi)容的實例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2017-12-12
  • 一篇文章帶你入門Java變量及整形

    一篇文章帶你入門Java變量及整形

    這篇文章主要介紹了簡單了解JAVA變量類型及代碼實例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2021-08-08
  • JDK1.7以上javaFTP上傳刪除文件的實現(xiàn)方法

    JDK1.7以上javaFTP上傳刪除文件的實現(xiàn)方法

    下面小編就為大家分享一篇JDK1.7以上javaFTP上傳刪除文件的實現(xiàn)方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2017-11-11
  • Mybatis分頁插件Pagehelper的PageInfo字段屬性使用及解釋

    Mybatis分頁插件Pagehelper的PageInfo字段屬性使用及解釋

    這篇文章主要介紹了Mybatis分頁插件Pagehelper的PageInfo字段屬性使用及解釋,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-05-05
  • java中的hashCode方法小例子

    java中的hashCode方法小例子

    這篇文章主要介紹了java中的hashCode方法小例子,有需要的朋友可以參考一下
    2013-12-12
  • java中xml進行報文發(fā)送和解析操作

    java中xml進行報文發(fā)送和解析操作

    這篇文章主要介紹了java中xml進行報文發(fā)送和解析操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-10-10
  • 淺談Java開發(fā)架構(gòu)之領(lǐng)域驅(qū)動設(shè)計DDD落地

    淺談Java開發(fā)架構(gòu)之領(lǐng)域驅(qū)動設(shè)計DDD落地

    DDD(Domain-Driven Design 領(lǐng)域驅(qū)動設(shè)計)是由Eric Evans最先提出,目的是對軟件所涉及到的領(lǐng)域進行建模,以應(yīng)對系統(tǒng)規(guī)模過大時引起的軟件復(fù)雜性的問題
    2021-06-06
  • spring boot實現(xiàn)驗證碼功能

    spring boot實現(xiàn)驗證碼功能

    Spring Boot是由Pivotal團隊提供的全新框架,其設(shè)計目的是用來簡化新Spring應(yīng)用的初始搭建以及開發(fā)過程。這篇文章主要介紹了spring boot實現(xiàn)驗證碼功能,需要的朋友可以參考下
    2018-04-04
  • Spring MVC學(xué)習(xí)之DispatcherServlet請求處理詳析

    Spring MVC學(xué)習(xí)之DispatcherServlet請求處理詳析

    這篇文章主要給大家介紹了關(guān)于Spring MVC學(xué)習(xí)教程之DispatcherServlet請求處理的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2018-11-11

最新評論