Java中BigDecimal,DateFormatter?和迭代器的"陷阱"
前言:
使用 IDEA 創(chuàng)建一個(gè) Maven 項(xiàng)目 calculate-date-traps 并導(dǎo)入 Junit 依賴。
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>在進(jìn)行計(jì)費(fèi)時(shí)使用 Double 和 Float 類型計(jì)算經(jīng)常會(huì)出現(xiàn)丟失精度的情況,在 test 包下新建一個(gè)測(cè)試類 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 類型進(jìn)行精確運(yùn)算出現(xiàn)了精度問題。
代碼中所使用的這些數(shù)最終都會(huì)轉(zhuǎn)換成二進(jìn)制,而浮點(diǎn)類型的數(shù)轉(zhuǎn)換成二進(jìn)制并不是精確地二進(jìn)制,只能是最接近的二進(jìn)制,這是應(yīng)為浮點(diǎn)數(shù)是由指數(shù)和尾數(shù)兩部分組成,所以在浮點(diǎn)數(shù)計(jì)算的過程中會(huì)出現(xiàn)丟失精度的問題。
如果恰巧計(jì)算結(jié)果的二進(jìn)制能和十進(jìn)制準(zhǔn)確轉(zhuǎn)換那么自然也就不會(huì)出現(xiàn)丟失精度的問題了。浮點(diǎn)數(shù)并不適合進(jìn)行精確計(jì)算而更適合科學(xué)計(jì)算。而 BigDecimal 類型的核心就是精度,在 test 包下新建一個(gè)測(cè)試類 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ù)點(diǎn)的位數(shù)比原來小會(huì)報(bào)錯(cuò)。設(shè)置為5,會(huì)自動(dòng)補(bǔ)上0,再次執(zhí)行測(cè)試輸出結(jié)果如下:

只想保留兩位數(shù)字,如何解決?如何對(duì)原始數(shù)字進(jìn)行舍入?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

測(cè)試其他舍入方式,除法運(yùn)算,除不盡出現(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ù)點(diǎn)的位數(shù)和指定的舍入方式
精度問題導(dǎo)致結(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)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
java 數(shù)據(jù)結(jié)構(gòu)基本算法希爾排序
這篇文章主要介紹了數(shù)據(jù)結(jié)構(gòu)基本算法希爾排序的相關(guān)資料,需要的朋友可以參考下2017-08-08
三種SpringBoot中實(shí)現(xiàn)異步調(diào)用的方法總結(jié)
Spring Boot 提供了多種方式來實(shí)現(xiàn)異步任務(wù),這篇文章主要為大家介紹了常用的三種實(shí)現(xiàn)方式,文中的示例代碼講解詳細(xì),需要的可以參考一下2023-05-05
詳解java實(shí)現(xiàn)簡(jiǎn)單掃碼登錄功能(模仿微信網(wǎng)頁版掃碼)
Java spring webmvc如何實(shí)現(xiàn)控制反轉(zhuǎn)
Spring?AOP操作的相關(guān)術(shù)語及環(huán)境準(zhǔn)備
學(xué)習(xí)Java設(shè)計(jì)模式之觀察者模式
詳解Java的堆內(nèi)存與棧內(nèi)存的存儲(chǔ)機(jī)制

