前言: 互聯網公司,對于BigDecimal的使用,還是較為頻繁的,那么就會涉及到關于這個類型的種種問題.
1:為什么使用BigDecimal 首先java八大基本類型真的很基本,4個整型搞不了小數,double和float搞的了小數,但搞不好,關鍵時刻就調鏈子,當然這也和他們存儲方式有關(二進制無法精確的表示1/10),天生注定搞不了精密計算,尤其是和錢相關的.
所以一般我們對于精密點的計算和涉及貨幣的計算,都會使用BigDecimal.他的出現,就是為了解決基本數據類型浮點數不能進行精確計算的問題.
2:如何使用BigDecimal 就說最常用的: 2.1.初始化,一般使用這個構造方法:new BigDecimal(String value); 其他的不再多說,某度很多,只能說我們一般都會用這個String類型的入參
關于BigDecimal的初始化,有一個坑要注意,就是盡量使用String類型的去初始化。
不信的話,可以看看下面的例子:BigDecimal a
= new BigDecimal ( 1.01 ) ; BigDecimal b
= new BigDecimal ( 1.02 ) ; BigDecimal c
= new BigDecimal ( "1.01" ) ; BigDecimal d
= new BigDecimal ( "1.02" ) ; System
. out
. println ( a
. add ( b
) ) ; System
. out
. println ( c
. add ( d
) ) ;
最終的打印結果是:
2.0300000000000000266453525910037569701671600341796875
2.03
很明顯,也是精度問題。這塊要注意。
2.2.基本運算
add
( BigDecimal
) BigDecimal對象中的值相加,然后返回這個對象。
subtract
( BigDecimal
) BigDecimal對象中的值相減,然后返回這個對象。
multiply
( BigDecimal
) BigDecimal對象中的值相乘,然后返回這個對象。
divide
( BigDecimal
) BigDecimal對象中的值相除,然后返回這個對象。
toString
( ) 將BigDecimal對象中的值以字符串形式返回。
doubleValue
( ) 將BigDecimal對象中的值以雙精度數返回。
floatValue
( ) 將BigDecimal對象中的值以單精度數返回。
longValue
( ) 將BigDecimal對象中的值以長整數返回。
intValue
( ) 將BigDecimal對象中的值以整數返回。
3.采坑經驗(敲黑板的重點!!!) 3.1.將BigDecimal類性的值(10.1000)傳給頁面后,頁面展示的(10.1000)不是我們想要的(10.1),該怎么處理?
BigDecimal money
; public BigDecimal getMoney
( ) { return money
; } 最開始上面的這種處理方式
, 如果money是
10.1000 , 那么get方法也會拿到
10.1000 , 但其實我們想要的是
10.1 就好了
.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 那怎么辦
, 直接上最終版
( 重寫個getMoneyString方法
) : public String getMoneyString
( ) { return money
. stripTrailingZeros
( ) . toPlainString
( ) ; } 這個方法返回的
, 就是
10.1 , String類型的
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 解釋下
: 1. stripTrailingZeros
( ) 方法官方文檔對返回的解釋是
: a numerically equal BigDecimal
with any trailing zeros removed
. 而且從方法名就可以看出來
, 就是去掉末尾的
0 . 那么
, 為什么還要用toPlainString
( ) 方法呢?看個例子
: new BigDecimal
( "60000.000" ) . stripTrailingZeros
( ) ; 這個結果是
6E + 4 , 而不是我們想要的
60000 , 而且官方文檔上也說明了
, 返回的值
, 會用科學計數法來表示
, 所以看下個方法
2. toPlainString
( ) 官方文檔對返回的解釋是
: a string representation of this BigDecimal without an exponent field
. 就是返回一個不用指數表示的字符串形式的值
. 所以兩個方法連用
, 就可以達到對BigDecimal的初步控制
.
3.2.值的比較用compareTo,不要用equals compareTo:左邊比右邊數大,返回1,相等返回0,比右邊小返回-1 equals:BigDecimal重寫了equals,比較的是數值
3.3.除法要養成習慣去設置精度,以免出現無限循環的小數而拋異常 (java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result)
new BigDecimal
( "10" ) . divide
( new BigDecimal
( "3" ) ) ;
這個就會拋出上面的異常
. 所以要用下面的new BigDecimal
( "10" ) . divide
( new BigDecimal
( "3" ) , 4 , BigDecimal
. ROUND_HALF_DOWN
) ;
這個代表
10 除以
3 , 結果保留
4 位小數
, 采用四舍五入保留
所以結果就是
: 3.3333
3.4.既然用了BigDecimal了,就應避免再與浮點類型互相轉換,否則精度會受很大的影響
4.BigDecimal格式化 可以使用NumberFormat類的format(BigDecimal)方法,利用NumberFormat不同類型的實例,對BigDecimal轉換不同的格式.詳細可以查查NumberFormat的各種實例方法,比如: NumberFormat.getCurrencyInstance(); NumberFormat.getCurrencyInstance(); NumberFormat.getInstance(); … 根據不同的需求,使用不同的格式… 下面提供兩個現成的轉換精度的方法
public static String
formatToStringWithTwoPlaces ( BigDecimal obj
) { DecimalFormat df
= new DecimalFormat ( "#.00" ) ; if ( obj
. compareTo ( BigDecimal
. ZERO
) == 0 ) { return "0.00" ; } else if ( obj
. compareTo ( BigDecimal
. ZERO
) > 0 && obj
. compareTo ( new BigDecimal ( 1 ) ) < 0 ) { return "0" + df
. format ( obj
) . toString ( ) ; } else { return df
. format ( obj
) . toString ( ) ; } } public static String
getDecimalStr ( BigDecimal bd
) { String bdStr
; if ( bd
!= null
) { bdStr
= bd
. setScale ( 2 , RoundingMode
. HALF_EVEN
) . toPlainString ( ) ; } else { bdStr
= "0.00" ; } return bdStr
; } public static void main ( String
[ ] args
) { BigDecimal bigDecimal1
= new BigDecimal ( "0" ) ; System
. out
. println ( formatToStringWithTwoPlaces ( bigDecimal1
) ) ; BigDecimal bigDecimal11
= new BigDecimal ( "0.6" ) ; System
. out
. println ( formatToStringWithTwoPlaces ( bigDecimal11
) ) ; BigDecimal bigDecimal12
= new BigDecimal ( "0.6666" ) ; System
. out
. println ( formatToStringWithTwoPlaces ( bigDecimal12
) ) ; BigDecimal bigDecimal2
= new BigDecimal ( "2" ) ; System
. out
. println ( formatToStringWithTwoPlaces ( bigDecimal2
) ) ; BigDecimal bigDecimal3
= new BigDecimal ( "2.1" ) ; System
. out
. println ( formatToStringWithTwoPlaces ( bigDecimal3
) ) ; BigDecimal bigDecimal4
= new BigDecimal ( "2.22" ) ; System
. out
. println ( formatToStringWithTwoPlaces ( bigDecimal4
) ) ; BigDecimal bigDecimal5
= new BigDecimal ( "2.333" ) ; System
. out
. println ( formatToStringWithTwoPlaces ( bigDecimal5
) ) ; BigDecimal bigDecimal15
= new BigDecimal ( "0" ) ; System
. out
. println ( getDecimalStr ( bigDecimal15
) ) ; BigDecimal bigDecimal115
= new BigDecimal ( "0.6" ) ; System
. out
. println ( getDecimalStr ( bigDecimal115
) ) ; BigDecimal bigDecimal125
= new BigDecimal ( "0.6666" ) ; System
. out
. println ( ConvertUtil
. getDecimalStr ( bigDecimal125
) ) ; BigDecimal bigDecimal25
= new BigDecimal ( "2" ) ; System
. out
. println ( getDecimalStr ( bigDecimal25
) ) ; BigDecimal bigDecimal35
= new BigDecimal ( "2.1" ) ; System
. out
. println ( getDecimalStr ( bigDecimal35
) ) ; BigDecimal bigDecimal45
= new BigDecimal ( "2.22" ) ; System
. out
. println ( getDecimalStr ( bigDecimal45
) ) ; BigDecimal bigDecimal55
= new BigDecimal ( "2.333" ) ; System
. out
. println ( getDecimalStr ( bigDecimal55
) ) ; }
5.BigDecimal取整
public static void main ( String
[ ] args
) { BigDecimal bigDecimal
= new BigDecimal ( 6.66 ) ; BigDecimal divide
= bigDecimal
. divide ( BigDecimal
. valueOf ( 6 ) , 0 , BigDecimal
. ROUND_UP
) ; System
. out
. println ( divide
) ; BigDecimal divide2
= bigDecimal
. divide ( BigDecimal
. valueOf ( 6 ) , BigDecimal
. ROUND_UP
) ; System
. out
. println ( divide2
) ; BigDecimal bigDecimal1
= divide2
. setScale ( 0 , BigDecimal
. ROUND_UP
) ; System
. out
. println ( bigDecimal1
) ; BigDecimal divide1
= bigDecimal
. divide ( BigDecimal
. valueOf ( 6 ) ) ; System
. out
. println ( divide1
) ; }
各個roundingMode詳解如下: ROUND_UP:非0時,舍棄小數后(整數部分)加1,比如1.11結果為2,-1.11結果為 -2 ROUND_DOWN:直接舍棄小數 ROUND_CEILING:如果 BigDecimal 是正的,則做 ROUND_UP 操作;如果為負,則做 ROUND_DOWN 操作 (一句話:取附近較大的整數) ROUND_FLOOR: 如果 BigDecimal 是正的,則做 ROUND_DOWN 操作;如果為負,則做 ROUND_UP 操作(一句話:取附近較小的整數) ROUND_HALF_UP:四舍五入(取更近的整數) ROUND_HALF_DOWN:跟ROUND_HALF_UP 差別僅在于0.5時會向下取整 ROUND_HALF_EVEN:取最近的偶數 ROUND_UNNECESSARY:不需要取整,如果存在小數位,就拋ArithmeticException 異常
總結
以上是生活随笔 為你收集整理的BigDecimal的个人总结 的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔 網站內容還不錯,歡迎將生活随笔 推薦給好友。