最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

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

在金融領域,為了保證數(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代碼塊(這塊是關鍵):

  • 首先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對象:

結論

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

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

相關文章

  • 基于IOC容器實現(xiàn)管理mybatis過程解析

    基于IOC容器實現(xiàn)管理mybatis過程解析

    這篇文章主要介紹了基于IOC容器實現(xiàn)管理mybatis過程解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-07-07
  • Mybatis實現(xiàn)一對多映射處理

    Mybatis實現(xiàn)一對多映射處理

    MyBatis是一種流行的Java持久化框架,這篇文章主要為大家介紹了Mybatis如何實現(xiàn)一對多映射處理,文中的示例代碼講解詳細,需要的可以參考下
    2023-08-08
  • Java面試Socket編程常用參數(shù)設置源碼問題分析

    Java面試Socket編程常用參數(shù)設置源碼問題分析

    這篇文章主要為大家介紹了Java編程中關于Socket結構分析,常用參數(shù)設置源碼示例以及面試中的問題分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助
    2022-03-03
  • 關于Java中Clonable接口和深拷貝詳解

    關于Java中Clonable接口和深拷貝詳解

    Cloneable是一個接口,實現(xiàn)這個接口后,可以在類中重寫Object中的clone方法,然后通過類調(diào)用clone方法進行克隆,這篇文章主要介紹了關于Java中Clonable接口和深拷貝的相關資料,需要的朋友可以參考下
    2026-01-01
  • SpringBoot的啟動過程源碼詳細分析

    SpringBoot的啟動過程源碼詳細分析

    這篇文章主要介紹了SpringBoot的啟動過程源碼詳細分析,SpringBoot啟動的時候,會構造一個SpringApplication的實例,構造SpringApplication的時候會進行初始化的工作,需要的朋友可以參考下
    2023-11-11
  • springboot結合easyexcel實現(xiàn)動態(tài)表頭的實踐

    springboot結合easyexcel實現(xiàn)動態(tài)表頭的實踐

    這篇文章主要介紹了springboot結合easyexcel實現(xiàn)動態(tài)表頭的實踐,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2025-06-06
  • Java進階教程之String類

    Java進階教程之String類

    這篇文章主要介紹了Java進階教程之String類,String類對象是不可變對象(immutable object),String類是唯一一個不需要new關鍵字來創(chuàng)建對象的類,需要的朋友可以參考下
    2014-09-09
  • Java中消息隊列任務的平滑關閉詳解

    Java中消息隊列任務的平滑關閉詳解

    對于消息隊列的監(jiān)聽,我們一般使用Java寫一個獨立的程序,在Linux服務器上運行。程序啟動后,通過消息隊列客戶端接收消息,放入一個線程池進行異步處理,并發(fā)的快速處理。這篇文章主要給大家介紹了關于Java中消息隊列任務的平滑關閉的相關資料,需要的朋友可以參考下。
    2017-11-11
  • 淺談springboot如何保證多線程安全

    淺談springboot如何保證多線程安全

    這篇文章主要介紹了springboot如何保證多線程安全,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-12-12
  • idea?maven依賴引入失效無法正常導入依賴問題的解決方法

    idea?maven依賴引入失效無法正常導入依賴問題的解決方法

    有時候idea導入一個新項目,或者pom文件修改(新增)了依賴,pom文件和代碼會報紅,提示依賴包不存在,下面這篇文章主要給大家介紹了關于idea?maven依賴引入失效無法正常導入依賴問題的解決方法,需要的朋友可以參考下
    2023-04-04

最新評論

夏河县| 庆城县| 利辛县| 汶川县| 察隅县| 遂宁市| 五莲县| 芦溪县| 兴城市| 阿勒泰市| 克什克腾旗| 吉首市| 阳山县| 乌兰浩特市| 项城市| 木兰县| 鄯善县| 自治县| 清镇市| 嘉兴市| 扶风县| 鄢陵县| 偏关县| 资阳市| 门源| 道孚县| 清水河县| 白朗县| 浦城县| 仁寿县| 永登县| 宜春市| 营山县| 锦屏县| 山阳县| 科技| 泉州市| 洛浦县| 沁水县| 东阳市| 海阳市|