Java中BigDecimal,DateFormatter?和迭代器的"陷阱"
前言:
使用 IDEA 創(chuàng)建一個 Maven 項目 calculate-date-traps 并導入 Junit 依賴。
<dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency>
在進行計費時使用 Double 和 Float 類型計算經(jīng)常會出現(xiàn)丟失精度的情況,在 test 包下新建一個測試類 ScaleLostTest。
public class ScaleLostTest { @Test public void testDoubleLostScale(){ double alpha = 1; double bravo = 20.2; double charlie = 400.03; System.out.println(alpha + bravo + charlie); } }
執(zhí)行上述代碼,輸出結(jié)果如下 :
使用 Double 類型進行精確運算出現(xiàn)了精度問題。
代碼中所使用的這些數(shù)最終都會轉(zhuǎn)換成二進制,而浮點類型的數(shù)轉(zhuǎn)換成二進制并不是精確地二進制,只能是最接近的二進制,這是應為浮點數(shù)是由指數(shù)和尾數(shù)兩部分組成,所以在浮點數(shù)計算的過程中會出現(xiàn)丟失精度的問題。
如果恰巧計算結(jié)果的二進制能和十進制準確轉(zhuǎn)換那么自然也就不會出現(xiàn)丟失精度的問題了。浮點數(shù)并不適合進行精確計算而更適合科學計算。而 BigDecimal 類型的核心就是精度,在 test 包下新建一個測試類 BigDecimalTest
public class BigDecimalTest { @Test public void testScaleException(){ BigDecimal bigDecimal = new BigDecimal("12138.121"); BigDecimal res = bigDecimal.setScale(2); System.out.println(res); } }
執(zhí)行上述代碼,輸出結(jié)果如下:
設置的精度既小數(shù)點的位數(shù)比原來小會報錯。設置為5,會自動補上0,再次執(zhí)行測試輸出結(jié)果如下:
只想保留兩位數(shù)字,如何解決?如何對原始數(shù)字進行舍入?BigDecimal支持的舍入方式有很多中,向上取整,向下取整,四舍五入等
@Test public void testChangeScale(){ BigDecimal bigDecimal = new BigDecimal("12138.121"); BigDecimal res = bigDecimal.setScale(2, BigDecimal.ROUND_HALF_UP); System.out.println(res); }
12138.128
測試其他舍入方式,除法運算,除不盡出現(xiàn)異常問題,除不盡,既無限循環(huán)的問題
@Test public void testDivideException(){ BigDecimal d1 = new BigDecimal(10); BigDecimal d2 = new BigDecimal(3); System.out.println(d1.divide(d2)); }
@Test public void testSolveDivideException(){ BigDecimal d1 = new BigDecimal(10); BigDecimal d2 = new BigDecimal(3); System.out.println(d1.divide(d2, 2, BigDecimal.ROUND_HALF_UP)); }
指定精度和舍入方式
總結(jié):使用BigDecimal一定要指定保留小數(shù)點的位數(shù)和指定的舍入方式
精度問題導致結(jié)果比較不一致:
@Test public void testCompare(){ BigDecimal d1 = new BigDecimal("0"); BigDecimal d2 = new BigDecimal("0.0"); System.out.println(d1.equals(d2)); System.out.println(d1.compareTo(d2)); }
equals()方法,精度不同直接返回false
到此這篇關(guān)于Java中BigDecimal,DateFormatter 和迭代器的"陷阱"的文章就介紹到這了,更多相關(guān)java 迭代器陷阱內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
springboot+thymeleaf 文件上傳功能的實現(xiàn)代碼
這篇文章主要介紹了springboot+thymeleaf 文件上傳功能的實現(xiàn)代碼,代碼簡單易懂,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-11-11在攔截器中讀取request參數(shù),解決在controller中無法二次讀取的問題
這篇文章主要介紹了在攔截器中讀取request參數(shù),解決在controller中無法二次讀取的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-10-10SpringCloud超詳細講解負載均衡組件Ribbon源碼
在微服務中,對服務進行拆分之后,必然會帶來微服務之間的通信需求,而每個微服務為了保證高可用性,又會去部署集群,那么面對一個集群微服務進行通信的時候,如何進行負載均衡也是必然需要考慮的問題2022-07-07分享我的第一次java Selenium自動化測試框架開發(fā)過程
這篇文章主要介紹了分享我的第一次java Selenium自動化測試框架開發(fā)過程,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2021-03-03Java Builder Pattern建造者模式詳解及實例
這篇文章主要介紹了Java Builder Pattern建造者模式詳解及實例的相關(guān)資料,需要的朋友可以參考下2017-01-01