Java使用BigDecimal公式精確計(jì)算及精度丟失問(wèn)題
一、Java使用BigDecimal公式計(jì)算(精確計(jì)算)
介紹:
使用BigDecimal加減乘除方法運(yùn)算,可以使用BigDecimal類提供的add、subtract、multiply、divide方法函數(shù)實(shí)現(xiàn)。
公式加法計(jì)算~add
public static void main(String[] args){ BigDecimal a = BigDecimal.valueOf(5.6); BigDecimal b = BigDecimal.valueOf(2.1); //BigDecimal計(jì)算add BigDecimal addResult = a.add(b); System.out.println("結(jié)果集: " +addResult); }
結(jié)果集:
公式減法計(jì)算~subtract
public static void main(String[] args){ BigDecimal a = BigDecimal.valueOf(5.6); BigDecimal b = BigDecimal.valueOf(2.1); BigDecimal計(jì)算subtract BigDecimal subtract = a.subtract(b); System.out.println("結(jié)果集subtract: " +subtract); }
結(jié)果集:
公式乘法計(jì)算~multiply
public static void main(String[] args){ BigDecimal a = BigDecimal.valueOf(5.6); BigDecimal b = BigDecimal.valueOf(2.1); BigDecimal計(jì)算multiply BigDecimal multiply = a.multiply(b); System.out.println("結(jié)果集: " +multiply); }
結(jié)果集:
公式除法計(jì)算~divide
public static void main(String[] args){ BigDecimal a = BigDecimal.valueOf(5.6); BigDecimal b = BigDecimal.valueOf(2.1); //BigDecimal計(jì)算divide //ROUND_HALF_UP:向“最接近的”整數(shù)舍入。 若舍入位大于等于5,則對(duì)舍入部分的前一位數(shù)字加1;若舍入位小于5,則直接舍棄。即為四舍五入模式。 BigDecimal divide = a.divide(b,2,BigDecimal.ROUND_HALF_UP);//四舍五入,保留兩位小數(shù). System.out.println("結(jié)果集: " +divide); }
結(jié)果集:
二、 BigDecimal(舍入模式)選擇
簡(jiǎn)介:
BigDecimal.setScale主要用于對(duì)BigDecimal數(shù)據(jù)小數(shù)點(diǎn)后的位數(shù)進(jìn)行 進(jìn)位、舍位、截?cái)嗟炔僮?/p>
java.math.RoundingMode:這是一種枚舉類型,它定義了8種數(shù)據(jù)的舍入模式。它與java.math.BigDecimal類中定義的8個(gè)同名靜態(tài)常量的作用相同,可用BigDecimal.setScale(int newScale, RoundingMode roundingMode)來(lái)設(shè)置數(shù)據(jù)的精度和舍入模式。
1、ROUND_UP:向遠(yuǎn)離零的方向舍入。
若舍入位為非零,則對(duì)舍入部分的前一位數(shù)字加1;若舍入位為零,則直接舍棄。即為向外取整模式。
2、ROUND_DOWN:向接近零的方向舍入。
不論舍入位是否為零,都直接舍棄。即為向內(nèi)取整模式。
3、ROUND_CEILING:向正無(wú)窮大的方向舍入。
若 BigDecimal 為正,則舍入行為與 ROUND_UP 相同;若為負(fù),則舍入行為與 ROUND_DOWN 相同。即為向上取整模式。
4、ROUND_FLOOR:向負(fù)無(wú)窮大的方向舍入。
若 BigDecimal 為正,則舍入行為與 ROUND_DOWN 相同;若為負(fù),則舍入行為與 ROUND_UP 相同。即為向下取整模式。
5、ROUND_HALF_UP:向“最接近的”整數(shù)舍入。
若舍入位大于等于5,則對(duì)舍入部分的前一位數(shù)字加1;若舍入位小于5,則直接舍棄。即為四舍五入模式。
6、ROUND_HALF_DOWN:向“最接近的”整數(shù)舍入。
若舍入位大于5,則對(duì)舍入部分的前一位數(shù)字加1;若舍入位小于等于5,則直接舍棄。即為五舍六入模式。
7、ROUND_HALF_EVEN:向“最接近的”整數(shù)舍入。
若(舍入位大于5)或者(舍入位等于5且前一位為奇數(shù)),則對(duì)舍入部分的前一位數(shù)字加1;
若(舍入位小于5)或者(舍入位等于5且前一位為偶數(shù)),則直接舍棄。即為銀行家舍入模式。
8、ROUND_UNNECESSARY
斷言請(qǐng)求的操作具有精確的結(jié)果,因此不需要舍入。
如果對(duì)獲得精確結(jié)果的操作指定此舍入模式,則拋出ArithmeticException。
案例:
public static void main(String[] args){ BigDecimal a = BigDecimal.valueOf(5.6); BigDecimal b = BigDecimal.valueOf(2.1); //BigDecimal計(jì)算divide //ROUND_HALF_UP:向“最接近的”整數(shù)舍入。 若舍入位大于等于5,則對(duì)舍入部分的前一位數(shù)字加1;若舍入位小于5,則直接舍棄。即為四舍五入模式。 //ROUND_UP:向遠(yuǎn)離零的方向舍入。 若舍入位為非零,則對(duì)舍入部分的前一位數(shù)字加1;若舍入位為零,則直接舍棄。即為向外取整模式。 BigDecimal divide = a.divide(b,BigDecimal.ROUND_HALF_UP, 2).setScale(2,ROUND_UP); System.out.println("結(jié)果集: " +divide); }
結(jié)果集:
計(jì)算器結(jié)果集如下圖:
三、 BigDecimal.setScale用法案例
BigDecimal.setScale主要用于對(duì)BigDecimal數(shù)據(jù)小數(shù)點(diǎn)后的位數(shù)進(jìn)行 進(jìn)位、舍位、截?cái)嗟炔僮?/strong>
public static void main(String[] args){ BigDecimal a = BigDecimal.valueOf(5.6); BigDecimal b = BigDecimal.valueOf(2.1); //BigDecimal計(jì)算divide BigDecimal divide = a.divide(b,2,BigDecimal.ROUND_UP).setScale(2, BigDecimal.ROUND_UP); System.out.println("結(jié)果集: " +divide); }
結(jié)果集:
四、Java使用BigDecimal精度丟失問(wèn)題
介紹:
在實(shí)際應(yīng)用中,經(jīng)常會(huì)使用到計(jì)算,舉例如 '銀行' 特別是在我們交易的時(shí)候,計(jì)算結(jié)果要求的更加精確,這個(gè)時(shí)候我們就會(huì)使用到j(luò)ava.math包中提供的API類BigDecimal,用于對(duì)超過(guò)16位有效位數(shù)的數(shù)字進(jìn)行精確的計(jì)算。
以如下代碼為例:
public static void main(String[] args){ System.out.println("使用bigDecimal進(jìn)行轉(zhuǎn)換"+new BigDecimal(234.567)); }
運(yùn)行后結(jié)果集出現(xiàn)精度丟失:
結(jié)果可以看出使用new BigDecimal(234.567),傳入?yún)?shù)為double類型發(fā)生精度丟失,運(yùn)行的結(jié)果并不等于234.567,而是為234.5670000000000072759576141834259033203125。
原因是double不能表示為任何有限長(zhǎng)度的二進(jìn)制小數(shù);
解決方法: 使用new BigDecimal(String)構(gòu)造函數(shù),創(chuàng)建一個(gè)參數(shù)以字符串表示數(shù)值的對(duì)象
public static void main(String[] args){ double a = 234.567; String b = "234.567"; // 方式一:double的封裝類Double中的toString()方法解決 System.out.println("使用bigDecimal進(jìn)行轉(zhuǎn)換" + new BigDecimal(new Double(a).toString())); // 方式二:使用String接收數(shù)值 System.out.println("使用bigDecimal進(jìn)行轉(zhuǎn)換" + new BigDecimal(b)); }
結(jié)果集如下:
如需使用加減乘除方法運(yùn)算,可以使用BigDecimal類提供的add、subtract、multiply、divide方法實(shí)現(xiàn) 如上:Java使用BigDecimal公式計(jì)算。
總結(jié)
到此這篇關(guān)于Java使用BigDecimal公式精確計(jì)算及精度丟失問(wèn)題的文章就介紹到這了,更多相關(guān)Java使用BigDecimal公式精確計(jì)算內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Postman實(shí)現(xiàn)傳List<String>集合
這篇文章主要介紹了Postman實(shí)現(xiàn)傳List<String>集合方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-08-08Java多線程 樂(lè)觀鎖和CAS機(jī)制詳細(xì)
這篇文章主要介紹了Java多線程 樂(lè)觀鎖和CAS機(jī)制,樂(lè)觀鎖是對(duì)于數(shù)據(jù)沖突保持一種樂(lè)觀態(tài)度,操作數(shù)據(jù)時(shí)不會(huì)對(duì)操作的數(shù)據(jù)進(jìn)行加鎖,需要的朋友可以參考下2021-10-10Map如何根據(jù)key指定條件進(jìn)行過(guò)濾篩選
這篇文章主要介紹了Map如何根據(jù)key指定條件進(jìn)行過(guò)濾篩選問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-09-09Java動(dòng)態(tài)代理分析及簡(jiǎn)單實(shí)例
這篇文章主要介紹了 Java動(dòng)態(tài)代理分析及簡(jiǎn)單實(shí)例的相關(guān)資料,需要的朋友可以參考下2017-02-02Redis實(shí)現(xiàn)商品秒殺功能頁(yè)面流程
這篇文章主要介紹了Redis實(shí)現(xiàn)商品秒殺功能的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-09-09