日韩成人免费在线_国产成人一二_精品国产免费人成电影在线观..._日本一区二区三区久久久久久久久不

當前位置:首頁 > 科技  > 軟件

不掌握 BigDecimal 的四大坑你敢用嗎?

來源: 責編: 時間:2024-05-30 17:18:01 250觀看
導讀BigDecimal 是 Java 中的一個類,這個相信大家都是知道的。它的作用就是可以表示任意精度的十進制數,BigDecimal 提供了精確的數字運算,適用于需要高精度計算的場景,例如金融、貨幣或者稅收等涉及到金錢的地方。與 double

BigDecimal 是 Java 中的一個類,這個相信大家都是知道的。它的作用就是可以表示任意精度的十進制數,BigDecimal 提供了精確的數字運算,適用于需要高精度計算的場景,例如金融、貨幣或者稅收等涉及到金錢的地方。lGs28資訊網——每日最新資訊28at.com

與 double 和 float 不同的是,BigDecimal 對象在計算的過程中不會丟失精度,那么下面我們就來看下第一個坑,浮點精度的坑。lGs28資訊網——每日最新資訊28at.com

lGs28資訊網——每日最新資訊28at.com

一、浮點精度的坑

我們先來看一個例子:lGs28資訊網——每日最新資訊28at.com

    public static void main(String[] args) {        BigDecimal num1 = new BigDecimal("0.1");        BigDecimal num2 = new BigDecimal("0.10");        // false        System.out.println(num1.equals(num2));        // 0        System.out.println(num1.compareTo(num2));    }

compareTo 方法比較中,a.compareTo(b)lGs28資訊網——每日最新資訊28at.com

返回:lGs28資訊網——每日最新資訊28at.com

  • -1: a小于b
  • 0: a等于b
  • 1: a大于b。

在上方的代碼中,我們使用 new BigDecimal 的形式 new 了兩個 BigDecimal 對象,分別是 0.1 和0.10。lGs28資訊網——每日最新資訊28at.com

我們分別使用了 equals 與 compareTo 進行比較,當使用 equals 進行比較時,返回了 false,這是因為 equals 不僅比較了值是否相等,還比較了精度是否相等,源碼中是這樣寫的:lGs28資訊網——每日最新資訊28at.com

 public boolean equals(Object x) {        if (!(x instanceof BigDecimal))            return false;        BigDecimal xDec = (BigDecimal) x;        if (x == this)            return true;        if (scale != xDec.scale)            return false;        long s = this.intCompact;        long xs = xDec.intCompact;        if (s != INFLATED) {            if (xs == INFLATED)                xs = compactValFor(xDec.intVal);            return xs == s;        } else if (xs != INFLATED)            return xs == compactValFor(this.intVal);        return this.inflated().equals(xDec.inflated());    }

所以在使用 equals 進行比較兩個 BigDecimal 的大小時,一定要注意這一點了。lGs28資訊網——每日最新資訊28at.com

簡單概括一下,如果比較兩個 BigDecimal 對象的大小,那就使用 compareTo 方法;如果嚴格比較精度的大小,那就使用 equals 方法進行比較。lGs28資訊網——每日最新資訊28at.com

上面我們知道了如何比較兩個 BigDecimal 對象的大小,equals 比較的還有他們的精度,那么精度又是如何設置的呢,這塊有沒有坑呢?lGs28資訊網——每日最新資訊28at.com

二、設置精度的坑

有的同學可能會說了,設置精度還有啥坑啊,設置了精度就好了嗎,哎對,就是這個意思,在做 BigDecimal 對象計算的時候,一定要設置精度。相反,有的同學就不喜歡設置精度,那么這 BUG 不就來了嗎。lGs28資訊網——每日最新資訊28at.com

來看一個例子:lGs28資訊網——每日最新資訊28at.com

    public static void main(String[] args) {        BigDecimal num1 = new BigDecimal("1");        BigDecimal num2 = new BigDecimal("3");        BigDecimal result = num1.divide(num2); // 默認舍入模式為 UNNECESSARY,會拋出 ArithmeticException    }

上述的代碼在執行結束之后會報錯 ArithmeticException ,這是因為默認舍入模式為 UNNECESSARY,所以會拋出 ArithmeticException。lGs28資訊網——每日最新資訊28at.com

Exception in thread "main" java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.

要解決這個異常也很容易,只需要加上精度即可。lGs28資訊網——每日最新資訊28at.com

    public static void main(String[] args) {        BigDecimal num1 = new BigDecimal("1");        BigDecimal num2 = new BigDecimal("3");        BigDecimal result = num1.divide(num2, 2,RoundingMode.HALF_UP);        // 輸出:0.33        System.out.println(result);    }

那么出現這個異常的原因是什么你考慮過嗎?為什么加了精度就不報錯了呢?lGs28資訊網——每日最新資訊28at.com

這個異常在源碼中也有說明:lGs28資訊網——每日最新資訊28at.com

lGs28資訊網——每日最新資訊28at.com

大概意思就是如果在做 divide 運算時,如果商是一個無限小數,而操作的結果是一個精確的數字,那么就會拋出該異常。lGs28資訊網——每日最新資訊28at.com

lGs28資訊網——每日最新資訊28at.com

不知道大家注意到一點沒有,就是上面做除法運算的時候,也就是 BigDecimal result = num1.divide(num2, 2,RoundingMode.HALF_UP); 這行代碼的位置,使用了一個新的變量 result 來接收結果值,因為 BigDecimal 是不可變的,因此每次進行運算都會創建一個新的 BigDecimal 對象,所以這一點也是需要注意的,創建的多了可能會產生大量的垃圾對象。lGs28資訊網——每日最新資訊28at.com

講完了精度與運算,那么你初始化的方式對嗎?lGs28資訊網——每日最新資訊28at.com

三、初始化的坑

先來看代碼:lGs28資訊網——每日最新資訊28at.com

BigDecimal num = new BigDecimal(0.1); // 使用雙精度浮點數構造System.out.println(num); // 輸出: 0.1000000000000000055511151231257827021181583404541015625BigDecimal num2 = new BigDecimal("0.1"); // 使用字符串構造System.out.println(num2); // 輸出: 0.1

在使用 new BigDecimal 構造器進行初始化的時候,如果有初始值,最好使用字符串的構造方法進行初始化。lGs28資訊網——每日最新資訊28at.com

lGs28資訊網——每日最新資訊28at.com

在使用 double 的構造器進行新建時,本身傳入的 0.1 就是浮點類型了,為了不丟失精度,在使用 new BigDecimal 新建時就把這個近似值完整的保留下來了。lGs28資訊網——每日最新資訊28at.com

或者就是 另外一種初始化方式 BigDecimal.valueOf(0.1);,通過看源碼可以發現,在 valueOf 的內部,將 Double 類型直接轉為了字符串了,因此也就不會存在精度丟失的問題了。lGs28資訊網——每日最新資訊28at.com

對于使用 new BigDecimal(0.1) 構造時,源碼中也已經說明了這個問題。lGs28資訊網——每日最新資訊28at.com

lGs28資訊網——每日最新資訊28at.com

大體意思就是生成的 BigDecimal 對象不是我們想要的 0.1,推薦使用 String 類型的構造方法。lGs28資訊網——每日最新資訊28at.com

lGs28資訊網——每日最新資訊28at.com

上面我們已經學會了如何初始化,如何運算,下一步就是如何用了,例如轉字符串,很多同學可能會說,轉字符串 toString() 不就好了,如果你也這樣想,那你單純了弟弟。lGs28資訊網——每日最新資訊28at.com

四、轉字符串的坑

還是先看一段代碼:lGs28資訊網——每日最新資訊28at.com

    public static void main(String[] args) {        BigDecimal a = BigDecimal.valueOf(89382389312389594.33822312317952678768725);        System.out.println(a.toString()); // 輸出:8.93823893123896E+16        String str = a.setScale(2, RoundingMode.HALF_UP).toString();        System.out.println(str); // 輸出: 89382389312389600.00    }

上面代碼中是一個非常大的數,我想把他轉為字符串,可是在使用 toString() 方法時,打印出來的卻是科學計數法。lGs28資訊網——每日最新資訊28at.com

所以如果想使用 toString() 方法進行轉字符串時,可以使用設置精度的方法,但是結果還是與我們的預期有所差別,我們想要的是一模一樣的打印出來呢?lGs28資訊網——每日最新資訊28at.com

那么 toPlainString 就上場了,這個方法返回一個字符串的表示形式,包含所有的有效數字。lGs28資訊網——每日最新資訊28at.com

代碼修改如下:lGs28資訊網——每日最新資訊28at.com

    public static void main(String[] args) {        BigDecimal a = BigDecimal.valueOf(89382389312389594.99933822312317952678768725);        System.out.println(a.toPlainString());    }

修改之后就可以了嗎,不可以,忘了上面說的嗎,使用 String 的構造函數吧兄弟,double 類型的構造函數會丟失精度的。lGs28資訊網——每日最新資訊28at.com

最終代碼如下:lGs28資訊網——每日最新資訊28at.com

    public static void main(String[] args) {        BigDecimal a = new BigDecimal("89382389312389594.99933822312317952678768725");        System.out.println(a.toPlainString());    }

除了上述兩種轉字符串的方法外,還有一種,就是 toEngineeringString,這個方法也是返回一個字符串,包含有效數字,但是它會使用工程計數法,科學計數法的一種變體,它使用數字的倍數來表示值,使得指數是 3 的倍數。例如,1000會顯示為"1E3",而不是"1E+3"。lGs28資訊網——每日最新資訊28at.com

所以總結就是:lGs28資訊網——每日最新資訊28at.com

  • toString:返回有效數字,必要的時候使用科學計數法。
  • toPlainString: 不實用任何科學計數法。
  • toEngineeringString:必要的時候使用工程計數法。

五、總結

本文從精度的比較、除法運算中是否設置精度、對象初始化到轉字符串,四個角度來把 BigDecimal 的坑盡可能清晰的描述出來,以及基于這些坑得到的優秀實踐。lGs28資訊網——每日最新資訊28at.com

有些場景下推薦使用 BigDecimal ,但是能不用還是不用,比 double 、float 多出來的性能損失得是你能接受的。如果非得用,那上面這幾個坑一定要規避。lGs28資訊網——每日最新資訊28at.com

本文鏈接:http://m.www897cc.com/showinfo-26-91825-0.html不掌握 BigDecimal 的四大坑你敢用嗎?

聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com

上一篇: C語言字符串為什么以/0 作為結束標志?

下一篇: 從0到1,手把手教你部署自己的線上項目

標簽:
  • 熱門焦點
Top 日韩成人免费在线_国产成人一二_精品国产免费人成电影在线观..._日本一区二区三区久久久久久久久不
在线播放国产一区中文字幕剧情欧美| 欧美精品一区二区三区在线播放| 一本色道久久综合| 99国产精品久久久久久久| 亚洲一区二区三区四区视频 | 亚洲深夜av| 午夜精品久久久久久99热软件 | 欧美日韩国产成人高清视频| 国产精品v欧美精品v日韩 | 久久蜜桃资源一区二区老牛 | 亚洲一区二区三区在线看| 欧美影院精品一区| 美女主播精品视频一二三四| 欧美日韩免费一区| 国产一区欧美| 99精品久久| 久久福利一区| 欧美理论电影在线观看| 国产精品一二三视频| 亚洲第一天堂av| 一区二区三区色| 久久亚洲精品欧美| 欧美午夜影院| 亚洲福利视频在线| 亚洲欧美另类综合偷拍| 蜜臀av一级做a爰片久久| 国产精品裸体一区二区三区| 在线观看91久久久久久| 亚洲综合色自拍一区| 欧美成人一区二免费视频软件| 国产精品久久久久久亚洲毛片| 激情小说另类小说亚洲欧美| 一区二区三区视频观看| 欧美插天视频在线播放| 国产欧美日韩三级| 99国产精品久久久久久久| 久久久久久久精| 国产精品激情偷乱一区二区∴| 永久久久久久| 小黄鸭精品密入口导航| 欧美高清不卡在线| 好吊色欧美一区二区三区四区| 中日韩在线视频| 欧美成人精品三级在线观看 | 好看的日韩av电影| 亚洲无线一线二线三线区别av| 免费不卡在线视频| 国产欧美一区二区三区在线看蜜臀 | 久久成人av少妇免费| 国产精品爱久久久久久久| 亚洲国产精选| 久久久久久久国产| 国产精品婷婷午夜在线观看| 夜夜精品视频| 欧美大片在线影院| 在线观看欧美日韩国产| 欧美一区二区三区婷婷月色 | 欧美亚州韩日在线看免费版国语版| 亚洲高清二区| 久久精品国产96久久久香蕉| 国产精品久久国产精麻豆99网站| 亚洲人成网站影音先锋播放| 久久久久一区二区三区| 国产毛片久久| 午夜精品理论片| 国产精品久久久久高潮| 亚洲天堂男人| 欧美性理论片在线观看片免费| 国产精品麻豆欧美日韩ww| 亚洲美女在线观看| 欧美极品色图| 亚洲国产一区二区a毛片| 久久综合精品国产一区二区三区| 黄色在线成人| 久久综合九色99| 在线电影欧美日韩一区二区私密| 久久久久久久久久久久久女国产乱| 国产亚洲va综合人人澡精品| 欧美一区二区三区精品电影| 国产欧美一区二区三区久久| 欧美一区二区高清| 国产亚洲精品久久久| 久久gogo国模裸体人体| 国产中文一区二区| 久久夜色精品国产噜噜av| 永久免费精品影视网站| 麻豆精品精品国产自在97香蕉| 在线观看一区视频| 欧美成人性生活| 99一区二区| 国产精品视频第一区| 欧美一级在线视频| 狠狠干综合网| 欧美aⅴ99久久黑人专区| 亚洲激情网站免费观看| 欧美理论在线播放| 亚洲深夜福利| 国产麻豆日韩| 久久亚洲私人国产精品va| 亚洲国产合集| 欧美日韩喷水| 性做久久久久久| 一区二区三区在线视频免费观看 | 欧美视频成人| 午夜免费日韩视频| 很黄很黄激情成人| 欧美成人黑人xx视频免费观看| 亚洲免费大片| 国产精品视频一二三| 久久精品国产亚洲精品| 在线日韩av永久免费观看| 欧美激情综合网| 亚洲男人天堂2024| 国产一区二区三区久久悠悠色av | 亚洲视频高清| 国产亚洲一区二区精品| 免费91麻豆精品国产自产在线观看| 亚洲精品一区二区三区蜜桃久| 欧美午夜片在线免费观看| 欧美影院成人| 亚洲全部视频| 国产精品美女久久久久久2018| 久久精品视频在线看| 亚洲精品黄色| 国产美女精品视频免费观看| 久久精品视频免费播放| 亚洲区免费影片| 国产精品久久夜| 久久午夜电影网| 一区二区三区日韩精品视频| 国产一区视频在线看| 欧美日本亚洲| 午夜精品免费在线| 亚洲精品欧美在线| 国产农村妇女毛片精品久久麻豆 | 国产精品久久久久久久浪潮网站| 久久视频国产精品免费视频在线| aa级大片欧美| 黄色日韩在线| 国产精品成av人在线视午夜片| 久久日韩粉嫩一区二区三区| 亚洲素人一区二区| 亚洲第一成人在线| 国产精品社区| 欧美精品性视频| 久久精品国产第一区二区三区最新章节 | 亚洲欧美另类中文字幕| 亚洲国产成人在线播放| 国产欧美成人| 欧美日韩免费在线| 鲁大师成人一区二区三区| 亚洲欧美成人一区二区三区| 91久久国产综合久久蜜月精品 | 亚洲天堂成人在线观看| 亚洲国产经典视频| 国产精品揄拍一区二区| 欧美久久视频| 久久亚洲精品一区二区| 亚洲一区二区三区乱码aⅴ| 亚洲国产免费看| 国内精品一区二区三区| 国产精品久久久久久久久果冻传媒| 欧美高清视频一区二区| 久久久午夜电影| 性色av一区二区三区在线观看| 亚洲最新合集| 亚洲欧洲精品一区二区三区| 国产综合视频| 国产欧美在线观看| 国产精品久久久久av| 欧美日韩国产综合视频在线观看| 蜜臀av性久久久久蜜臀aⅴ| 久久黄金**| 欧美亚洲免费高清在线观看| 亚洲午夜精品国产| 9人人澡人人爽人人精品| 亚洲精品色婷婷福利天堂| 亚洲第一精品电影| 红桃视频成人| 国产一区二区三区在线观看网站 | 亚洲精品国产精品国产自| 国内精品视频久久| 国产一区二区欧美日韩| 国产精品网站在线观看| 国产精品www994| 欧美日韩中文另类| 欧美日韩成人一区二区| 欧美成人精品h版在线观看| 久久永久免费| 久久久久久日产精品| 久久成人免费日本黄色| 欧美一区国产一区| 性欧美暴力猛交69hd| 亚洲欧美一区二区原创| 亚洲女性喷水在线观看一区| 亚洲午夜在线观看| 亚洲在线1234| 亚洲综合色激情五月| 亚洲综合激情| 午夜精品久久久久久久久| 午夜精品网站| 欧美亚洲综合在线| 久久成年人视频| 久久精品国产免费|