淺談Java基礎知識之BigDecimal
一、基本使用
使用示例:
// 初始化 BigDecimal bd1=new BigDecimal("456"); BigDecimal bd2=new BigDecimal("123"); // 加 BigDecimal add=bd1.add(bd2); // 減 BigDecimal subtract=bd1.subtract(bd2); // 乘 BigDecimal multiply=bd1.multiply(bd2); // 除 BigDecimal divide=bd1.divide(bd2); // 指數(shù)運算, 2 is exponent BigDecimal powerValue=bd2.pow(2); // 四舍五入 multiply.setScale(1, RoundingMode.HALF_EVEN);
二、舍入模式
枚舉類 java.math.RoundingMode
定義了8種數(shù)據(jù)的舍入模式,在 BigDecimal
中,可以用 BigDecimal.setScale(int newScale, RoundingMode roundingMode)
來設置數(shù)據(jù)的精度和舍入模式。
ROUND_UP
:向遠離零的方向舍入。- 若舍入位為非零,則對舍入部分的前一位數(shù)字加1;若舍入位為零,則直接舍棄。即為向外取整模式。
ROUND_DOWN
:向接近零的方向舍入。- 不論舍入位是否為零,都直接舍棄。即為向內(nèi)取整模式。
ROUND_CEILING
:向正無窮大的方向舍入。- 若
BigDecimal
為正,則舍入行為與ROUND_UP
相同;若為負,則舍入行為與ROUND_DOWN
相同。即為向上取整模式。 ROUND_FLOOR
:向負無窮大的方向舍入。- 若
BigDecimal
為正,則舍入行為與ROUND_DOWN
相同;若為負,則舍入行為與ROUND_UP
相同。即為向下取整模式。 ROUND_HALF_UP
:向“最接近的”整數(shù)舍入。- 若舍入位大于等于5,則對舍入部分的前一位數(shù)字加1;若舍入位小于5,則直接舍棄。即為四舍五入模式。
ROUND_HALF_DOWN
:向“最接近的”整數(shù)舍入。- 若舍入位大于5,則對舍入部分的前一位數(shù)字加1;若舍入位小于等于5,則直接舍棄。即為五舍六入模式。
ROUND_HALF_EVEN
:向“最接近的”整數(shù)舍入。- 若(舍入位大于5)或者(舍入位等于5且前一位為奇數(shù)),則對舍入部分的前一位數(shù)字加1;
- 若(舍入位小于5)或者(舍入位等于5且前一位為偶數(shù)),則直接舍棄。即為銀行家舍入模式。
ROUND_UNNECESSARY
- 斷言請求的操作具有精確的結果,因此不需要舍入。
- 如果對獲得精確結果的操作指定此舍入模式,則拋出ArithmeticException。
三、注意事項
1.大量的數(shù)學計算時,使用 基本數(shù)據(jù)類型
而不是BigInteger
和 BigDecimal
。
原因:由于是不可變(immutable)的,在進行每一步運算時,都會產(chǎn)生一個新的對象,引起開銷。
建議:應盡量用long
,float
,double
等基本類型做科學計算或者工程計算。
設計的目的是用來精確地表示大整數(shù)和小數(shù),例如進行金額等比較敏感的數(shù)據(jù)運算。
2.構造 BigDecimal
時,使用 String
而不是 double
。
原因:有些數(shù)字用 double 根本無法精確表示,傳給 BigDecimal 構造方法時就已經(jīng)不精確了。例如:new BigDecimal(0.1)得到的值是0.1000000000000000055511151231257827021181583404541015625。
建議:使用 new BigDecimal(“0.1”) 得到的值是 0.1。
BigDecimal
有4個構造方法,其中的兩個用BigInteger
構造,一個用double
構造,一個用String
構造。
3.比較兩個 BigDecimal
值時,使用 compareTo()
而不是 equals()
。
原因: equals() 方法認為 0.1 和 0.1 是相等的,返回true;認為 0.10 和 0.1 是不等的,返回false。
compareTo() 方法則認為 0.1 與 0.1 相等,0.10 與 0.1 也相等。
4.另外還有一些情形,任意精度的小數(shù)運算仍不能表示精確結果。例如,1 除以 9 會產(chǎn)生無限循環(huán)的小數(shù) .111111…。
出于這個原因,在進行除法運算時,BigDecimal可以讓您顯式地控制舍入。
四、異常處理 ArithmeticException異常
在使用BigDecimal數(shù)據(jù)類型進行計算時,會有三種情況拋出 ArithmeticException
,分別是:
1.當除數(shù)為 0 時,這種情況比較常見,所以我們在進行除法運算之前先判斷下除數(shù)是否為 0;
2.如果運算的結果是無線循環(huán)的小數(shù),并且在除的時候沒有對結果設置精確的位數(shù);
BigDecimal divide 方法結果為無限小數(shù)問題 10/3=3.3333333333333333…
public static void main(String[] args) { BigDecimal a = new BigDecimal("10"); BigDecimal o = new BigDecimal("3"); System.out.print(a.divide(o,2, BigDecimal.ROUND_DOWN).doubleValue()); }
Note:不設置精度范圍會出現(xiàn)異常
3.當我們設置了結果的舍入模式是 ROUND_UNNECESSARY
模式時:
如果確保了計算的結果是精確的,則不會拋出異常;否則,就會拋出ArithmeticException
異常。
4.只設置精度(小數(shù)點后面的位數(shù),scale),但沒有設置舍入模式(roundingModel)時,會不知道如何對小數(shù)舍入而報錯。
所以在設置精度時要連舍入模式一起設置。
// wrong code bd = new BigDecimal(1.5); // is actually 1.4999.... bd.setScale(1); // throws ArithmeticException // wright code a = new BigDecimal("2.5"); // digit left of 5 is even, so round down b = new BigDecimal("1.5"); // digit left of 5 is odd, so round up a.setScale(0, BigDecimal.ROUND_HALF_EVEN).toString() // => 2 b.setScale(0, BigDecimal.ROUND_HALF_EVEN).toString() // => 2
5.指數(shù)運算,指數(shù) exponent 為負數(shù)時
If you are raising things to negative exponents, you must specify a MathContext in BigDecimal.pow(int, MathContext) so it knows how much precision to use – otherwise, BigDecimal will try to compute it to infinite precision, which is not possible for some values.
//wrong code BigDecimal powerValue=bd2.pow(-27);// -27 is exponent
到此這篇關于淺談Java基礎知識之BigDecimal的文章就介紹到這了,更多相關Java BigDecimal內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
SpringBoot啟動多數(shù)據(jù)源找不到合適的驅動類問題
這篇文章主要介紹了SpringBoot啟動多數(shù)據(jù)源找不到合適的驅動類問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-01-01Spring中ApplicationEvent事件機制源碼詳解
這篇文章主要介紹了Spring中ApplicationEvent事件機制源碼詳解,Spring中與事件有關的接口和類主要包括ApplicationEvent、ApplicationListener,下面來看一下Spring中事件的具體應用,需要的朋友可以參考下2023-09-09java kafka寫入數(shù)據(jù)到HDFS問題
這篇文章主要介紹了java kafka寫入數(shù)據(jù)到HDFS問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-08-08