成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

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

開發(fā) 前端
BigDecimal在計算時,實(shí)際會把數(shù)值擴(kuò)大10的n次倍,變成一個long型整數(shù)進(jìn)行計算,整數(shù)計算時自然可以實(shí)現(xiàn)精度不丟失。同時結(jié)合精度scale,實(shí)現(xiàn)最終結(jié)果的計算。

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

類介紹

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

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

從例子入手

通過debug來發(fā)現(xiàn)源碼中的奧秘是了解類運(yùn)行機(jī)制很好的方式。請看下面的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)上述提到的幾個屬性被賦了值:

圖片圖片

接下來進(jì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);
        }
    }
}

看一下傳進(jìn)來的值:

圖片圖片

進(jìn)入上面代碼塊第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,所以進(jìn)入到最下面的else代碼塊(這塊是關(guān)鍵):

首先17行校驗(yàn)了一下數(shù)值范圍

18行將ys擴(kuò)大了10的n次倍,這里n=raise=1,所以返回的scaledY=350

接著就進(jìn)入到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í)際會把數(shù)值擴(kuò)大10的n次倍,變成一個long型整數(shù)進(jìn)行計算,整數(shù)計算時自然可以實(shí)現(xiàn)精度不丟失。同時結(jié)合精度scale,實(shí)現(xiàn)最終結(jié)果的計算。

責(zé)任編輯:武曉燕 來源: 碼猿技術(shù)專欄
相關(guān)推薦

2021-03-08 10:19:59

MQ消息磁盤

2020-03-27 16:05:49

數(shù)據(jù)庫數(shù)據(jù)MySQL

2011-06-16 15:29:22

2013-03-13 03:58:12

馬云人大代表兩會

2022-01-11 10:29:32

Docker文件掛載

2016-10-11 16:31:56

微信服務(wù)器消息

2024-03-11 11:02:03

Date類JavaAPI

2024-11-29 08:20:22

Autowired場景項(xiàng)目

2024-12-06 08:20:22

BigDecimal浮點(diǎn)數(shù)初始化

2011-11-23 13:04:19

Java高精度BigDecimal

2022-08-24 10:58:31

數(shù)據(jù)丟失數(shù)據(jù)丟失防護(hù)

2023-12-13 10:36:38

Long算法代碼

2015-09-08 16:22:14

Facebook公有云云市場

2024-06-04 00:10:00

開發(fā)拷貝

2024-11-12 10:30:54

Docker部署數(shù)據(jù)庫

2021-05-19 09:37:45

SessionTokencookie

2013-09-03 15:20:49

創(chuàng)業(yè)日本人創(chuàng)業(yè)

2020-04-01 17:50:02

Python編程語言

2021-03-03 08:32:43

集成晶振MCU

2024-02-21 21:28:29

Linux系統(tǒng)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號

主站蜘蛛池模板: 日韩精品一区二区三区中文字幕 | 日韩视频一区二区在线 | 国产精品视频一二三区 | 国产成人精品一区二区三区四区 | 亚洲一区二区三区四区在线观看 | h视频在线看 | 久久精品中文字幕 | 亚洲国产片 | 一本色道精品久久一区二区三区 | 国产三级精品视频 | 欧美日韩亚 | 97免费视频在线观看 | 成人午夜免费视频 | 久久在线视频 | 日韩精品免费视频 | 亚洲啊v在线 | 国产精品色一区二区三区 | 欧美一区免费 | 日日草夜夜草 | 久久成人国产精品 | 蜜臀久久 | 国产精品视频一区二区三区不卡 | 欧美精品成人一区二区三区四区 | 欧美国产精品 | 成人欧美一区二区三区白人 | 亚洲国产欧美国产综合一区 | 我我色综合| 久久国产精品视频 | 午夜噜噜噜 | 99精品欧美一区二区蜜桃免费 | 天天综合天天 | 91在线视频网址 | 日韩欧美手机在线 | www.中文字幕.com | 亚洲精品电影网在线观看 | 精品九九九 | 欧美成人精品一区二区三区 | 99久久婷婷国产综合精品首页 | 国产在线精品一区二区 | 色综合久久天天综合网 | 国产精品美女久久久久久免费 |