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

Java中BigDecimal使用注意避坑指南

 更新時間:2023年02月20日 16:25:49   作者:Gangbb  
Java在java.math包中提供的API類BigDecimal,用來對超過16位有效位的數(shù)進(jìn)行精確的運(yùn)算,下面這篇文章主要給大家介紹了關(guān)于Java中BigDecimal使用注意避坑的相關(guān)資料,需要的朋友可以參考下

前言

在java.math包中提供了對大數(shù)字的操作類,用于進(jìn)行高精確計算,如BigInteger,BigDecimal類。而平常我們開發(fā)中使用最多的float和double只能適用于一般的科學(xué)和工程計算,如果要在比較精確的計算方面如貨幣,那么使用float和double會相應(yīng)的丟失精度,因此用于精密計算大數(shù)字的類BigDecimal就必不可少了。所以BigDecimal適合商業(yè)計算場景,用來對超過16位有效位的數(shù)進(jìn)行精確的運(yùn)算。但是BigDecimal的使用并不像float和double那樣,使用不當(dāng)造成的后果更嚴(yán)重,下面就來看下我們項目中踩過BigDecimal的坑:

一. BigDecimal的初始化精度丟失問題

先來看下面代碼的運(yùn)行結(jié)果:

BigDecimal bd1 = new BigDecimal(0.1);
System.out.println("bd1="+bd1);
BigDecimal bd2 = new BigDecimal("0.1");
System.out.println("bd2="+bd2);
BigDecimal bd3 = BigDecimal.valueOf(0.1);
System.out.println("bd3="+bd3);

輸出結(jié)果:

bd1=0.1000000000000000055511151231257827021181583404541015625
bd2=0.1
bd3=0.1

如果是float或double類型轉(zhuǎn)Bigdecimal,不要使用new BigDecimal()轉(zhuǎn), 使用valueOf()方法 或 new BigDecimal(“”)轉(zhuǎn)成string,否則有可能出現(xiàn)精度問題。

《Effective Java》這本書里說過:
如果需要精確的答案,請避免使用float和double

因為float和double執(zhí)行的是二進(jìn)制浮點運(yùn)算,二進(jìn)制有些情況下不能準(zhǔn)確的表示一個小數(shù),就像十進(jìn)制不能準(zhǔn)確的表示1/3(1/3=0.3333…)也就是說二進(jìn)制表示小數(shù)的時候只能夠表示能夠用1/(2^n)的和的任意組合,例如:

  • 0.5能夠表示,因為它可以表示成為1/2
  • 0.75也能夠表示,因為它可以表示成為1/2+1/(2^2)
  • 0.875也能夠表示,因為它可以表示成為1/2+1/(22)+1/(23)
  • 但是0.1不能夠精確表示,因為它不能夠表示成為1/(2^n)的和的形式
System.out.println(0.5*3);
System.out.println(0.1*3);

大家可以本地執(zhí)行下這兩行代碼,看下輸出結(jié)果就知道為什么二進(jìn)制不能表示0.1卻可以表示0.5了。所以其實不是BigDecimal的問題,BigDecimal就是為了滿足精確運(yùn)算存在的,問題出在0.1它本身就一個不準(zhǔn)確的值,這其實跟BigDecimal無關(guān),但在使用的時候需要注意用法。

二. BigDecimal在進(jìn)行除法運(yùn)算時需設(shè)置精度,否則對于除不盡的情況會拋出異常

繼續(xù)看下面的代碼執(zhí)行結(jié)果:

BigDecimal bd4 = new BigDecimal("10");
BigDecimal bd5 = new BigDecimal("3");
System.out.println(bd4.divide(bd5));

輸出結(jié)果:

Exception in thread "main" java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.
at java.math.BigDecimal.divide(BigDecimal.java:1690)
at BigDecimalTest.main(BigDecimalTest.java:38)

應(yīng)該向下面這樣設(shè)置小數(shù)點后的位數(shù),以及超出后是四舍五入和向上/向下取整或者直接舍棄:

System.out.println(bd4.divide(bd5,2,BigDecimal.ROUND_DOWN));

第二個參數(shù)表示小數(shù)位數(shù),第三個參數(shù)表示超出的位數(shù)直接舍棄(當(dāng)然也可以設(shè)置四舍五入,向上取整等)

三. 不要使用BigDecimal的equals方法比較大小, 否則可能會因為精度問題導(dǎo)致比較結(jié)果和預(yù)期的不一致

BigDecimal bd1 = new BigDecimal("0");
BigDecimal bd2 = new BigDecimal("0.0");
System.out.println(bd1.equals(bd2));
System.out.println(bd1.compareTo(bd2) == 0)

輸出結(jié)果:

equals:false
compareTo:true

如果你無法確定你的BigDecimal值有小數(shù)情況,最好用compareTo!

補(bǔ)充:BigDecimal比較值大小避坑

注意點

但是,對于BigDecimal的大小比較,用equals方法的話會不僅會比較值的大小,還會比較兩個對象的精確度,而compareTo方法則不會比較精確度,只比較數(shù)值的大小。這也是很多人比較容易踩的坑。下面給大家做一下示例:

 BigDecimal bigDecimal1 = new BigDecimal("1.350000000000");
 BigDecimal bigDecimal2 = new BigDecimal("1.35");
 System.out.println("bigdecial1:"+bigDecimal1);
 System.out.println("bigdecail2:"+bigDecimal2);
 System.out.println(bigDecimal1.equals(bigDecimal2)); //false
 System.out.println(bigDecimal1.compareTo(bigDecimal2)); // 0 代表相等

運(yùn)行結(jié)果:

bigdecial1:1.350000000000
bigdecail2:1.35
false
0

總結(jié)

到此這篇關(guān)于Java中BigDecimal使用注意避坑指南的文章就介紹到這了,更多相關(guān)Java BigDecimal使用避坑內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 解決FeignClient發(fā)送post請求異常的問題

    解決FeignClient發(fā)送post請求異常的問題

    這篇文章主要介紹了FeignClient發(fā)送post請求異常的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • Java反轉(zhuǎn)鏈表測試過程介紹

    Java反轉(zhuǎn)鏈表測試過程介紹

    這篇文章主要介紹了Java反轉(zhuǎn)鏈表測試過程,學(xué)習(xí)過數(shù)據(jù)結(jié)構(gòu)的小伙伴們,對鏈表想來是并不陌生。本篇文章將為大家介紹幾種在Java語言當(dāng)中,實現(xiàn)鏈表反轉(zhuǎn)的幾種方法,以下是具體內(nèi)容
    2023-04-04
  • Java中Cglib代理類重寫邏輯詳解

    Java中Cglib代理類重寫邏輯詳解

    這篇文章主要介紹了Java中Cglib代理類重寫邏輯詳解,代理類中只會維護(hù)NoOp這個回調(diào)屬性,并不會生成目標(biāo)類MyService中的noOp所對應(yīng)的方法,需要的朋友可以參考下
    2023-11-11
  • 使用kafka-console-consumer.sh不停報WARN的問題及解決

    使用kafka-console-consumer.sh不停報WARN的問題及解決

    這篇文章主要介紹了使用kafka-console-consumer.sh不停報WARN的問題及解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-03-03
  • Java 進(jìn)階必備之ssm框架全面整合

    Java 進(jìn)階必備之ssm框架全面整合

    SSM框架是spring MVC ,spring和mybatis框架的整合,是標(biāo)準(zhǔn)的MVC模式,將整個系統(tǒng)劃分為表現(xiàn)層,controller層,service層,DAO層四層,使用spring MVC負(fù)責(zé)請求的轉(zhuǎn)發(fā)和視圖管理,spring實現(xiàn)業(yè)務(wù)對象管理,mybatis作為數(shù)據(jù)對象的持久化引擎
    2021-10-10
  • Java BigDecimal類用法詳解

    Java BigDecimal類用法詳解

    BigDecimal 由任意精度的整數(shù)非標(biāo)度值 和32 位的整數(shù)標(biāo)度 (scale) 組成。如果為零或正數(shù),則標(biāo)度是小數(shù)點后的位數(shù)。如果為負(fù)數(shù),則將該數(shù)的非標(biāo)度值乘以 10 的負(fù)scale 次冪。
    2016-06-06
  • SpringBoot Admin 使用指南(推薦)

    SpringBoot Admin 使用指南(推薦)

    這篇文章主要介紹了SpringBoot Admin 使用指南(推薦),Spring Boot Admin 是一個管理和監(jiān)控你的 Spring Boot 應(yīng)用程序的應(yīng)用程序,非常具有實用價值,需要的朋友可以參考下
    2018-01-01
  • 如何用Intellij idea2020打包jar的方法步驟

    如何用Intellij idea2020打包jar的方法步驟

    這篇文章主要介紹了如何用Intellij idea 2020打包jar的方法步驟,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-04-04
  • java: 錯誤: 無效的源發(fā)行版18問題及解決

    java: 錯誤: 無效的源發(fā)行版18問題及解決

    這篇文章主要介紹了java: 錯誤: 無效的源發(fā)行版18問題及解決,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-04-04
  • Spring實戰(zhàn)之使用ClassPathResource加載xml資源示例

    Spring實戰(zhàn)之使用ClassPathResource加載xml資源示例

    這篇文章主要介紹了Spring實戰(zhàn)之使用ClassPathResource加載xml資源,結(jié)合實例形式分析了Spring使用ClassPathResource加載xml資源的具體實現(xiàn)步驟與相關(guān)操作技巧,需要的朋友可以參考下
    2019-12-12

最新評論

淮北市| 科尔| 胶州市| 龙岩市| 扎鲁特旗| 灵宝市| 桐梓县| 留坝县| 苏尼特左旗| 建始县| 改则县| 恩平市| 和静县| 达拉特旗| 汾西县| 鸡西市| 宁陕县| 通许县| 宁化县| 竹溪县| 鲁甸县| 罗平县| 宁远县| 东平县| 尼木县| 泰安市| 武乡县| 怀宁县| 黑龙江省| 中超| 青龙| 渑池县| 桦南县| 彭阳县| 喜德县| 汪清县| 定边县| 建德市| 龙海市| 昌平区| 承德县|