Java BigDecimal類用法詳解。本站提示廣大學習愛好者:(Java BigDecimal類用法詳解)文章只能為提供參考,不一定能成為您想要的結果。以下是Java BigDecimal類用法詳解正文
1.引言
借用《Effactive Java》這本書中的話,float和double類型的重要設計目的是為了迷信盤算和工程盤算。他們履行二進制浮點運算,這是為了在廣域數值規模上供給較為准確的疾速近似盤算而精心設計的。但是,它們沒有供給完整准確的成果,所以不該該被用於請求准確成果的場所。然則,貿易盤算常常請求成果准確,這時候候BigDecimal就派上年夜用處啦。
2.BigDecimal簡介
BigDecimal 由隨意率性精度的整數非標度值 和32 位的整數標度 (scale) 構成。假如為零或負數,則標度是小數點後的位數。假如為正數,則將該數的非標度值乘以 10 的負scale 次冪。是以,BigDecimal表現的數值是(unscaledValue × 10-scale)。
3.測試代碼
3.1結構函數(重要測試參數類型為double和String的兩個經常使用結構函數)
BigDecimal aDouble =new BigDecimal(1.22);
System.out.println("construct with a double value: " + aDouble);
BigDecimal aString = new BigDecimal("1.22");
System.out.println("construct with a String value: " + aString);
你以為輸入成果會是甚麼呢?假如你沒有以為第一個會輸入1.22,那末祝賀你答對了,輸入成果以下:
construct with a doublevalue:1.2199999999999999733546474089962430298328399658203125
construct with a String value: 1.22
JDK的描寫:
1、參數類型為double的結構辦法的成果有必定的弗成預知性。有人能夠以為在Java中寫入newBigDecimal(0.1)所創立的BigDecimal正好等於 0.1(非標度值 1,其標度為 1),然則它現實上等於0.1000000000000000055511151231257827021181583404541015625。這是由於0.1沒法精確地表現為 double(或許說關於該情形,不克不及表現為任何無限長度的二進制小數)。如許,傳入到結構辦法的值不會正好等於 0.1(固然外面上等於該值)。
2、另外一方面,String 結構辦法是完整可預知的:寫入 newBigDecimal("0.1") 將創立一個 BigDecimal,它正好等於預期的 0.1。是以,比擬而言,平日建議優先應用String結構辦法。
3、當double必需用作BigDecimal的源時,請留意,此結構辦法供給了一個精確轉換;它不供給與以下操作雷同的成果:先應用Double.toString(double)辦法,然後應用BigDecimal(String)結構辦法,將double轉換為String。要獲得該成果,請應用static valueOf(double)辦法。
3.2 加法操作
BigDecimal a =new BigDecimal("1.22");
System.out.println("construct with a String value: " + a);
BigDecimal b =new BigDecimal("2.22");
a.add(b);
System.out.println("aplus b is : " + a);
我們很輕易會以為會輸入:
construct with a Stringvalue: 1.22
a plus b is :3.44
但現實上a plus b is : 1.22
4.源碼剖析
4.1 valueOf(doubleval)辦法
public static BigDecimal valueOf(double val) {
// Reminder: a zero double returns '0.0', so we cannotfastpath
// to use the constant ZERO. This might be important enough to
// justify a factory approach, a cache, or a few private
// constants, later.
returnnew BigDecimal(Double.toString(val));//見3.1關於JDK描寫的第三點
}
4.2 add(BigDecimal augend)辦法
public BigDecimal add(BigDecimal augend) { long xs =this.intCompact; //整型數字表現的BigDecimal,例a的intCompact值為122 long ys = augend.intCompact;//同上 BigInteger fst = (this.intCompact !=INFLATED) ?null :this.intVal;//初始化BigInteger的值,intVal為BigDecimal的一個BigInteger類型的屬性 BigInteger snd =(augend.intCompact !=INFLATED) ?null : augend.intVal; int rscale =this.scale;//小數位數 long sdiff = (long)rscale - augend.scale;//小數位數之差 if (sdiff != 0) {//取小數位數多的為成果的小數位數 if (sdiff < 0) { int raise =checkScale(-sdiff); rscale =augend.scale; if (xs ==INFLATED || (xs = longMultiplyPowerTen(xs,raise)) ==INFLATED) fst =bigMultiplyPowerTen(raise); }else { int raise =augend.checkScale(sdiff); if (ys ==INFLATED ||(ys =longMultiplyPowerTen(ys,raise)) ==INFLATED) snd = augend.bigMultiplyPowerTen(raise); } } if (xs !=INFLATED && ys !=INFLATED) { long sum = xs + ys; if ( (((sum ^ xs) &(sum ^ ys))) >= 0L)//斷定有沒有溢出 return BigDecimal.valueOf(sum,rscale);//前往應用BigDecimal的靜態工場辦法獲得的BigDecimal實例 } if (fst ==null) fst =BigInteger.valueOf(xs);//BigInteger的靜態工場辦法 if (snd ==null) snd =BigInteger.valueOf(ys); BigInteger sum =fst.add(snd); return (fst.signum == snd.signum) ?new BigDecimal(sum,INFLATED, rscale, 0) : new BigDecimal(sum,compactValFor(sum),rscale, 0);//前往經由過程其他結構辦法獲得的BigDecimal對象 }
以上只是對加法源碼的剖析,減乘除其實終究都前往的是一個新的BigDecimal對象,由於BigInteger與BigDecimal都是弗成變的(immutable)的,在停止每步運算時,都邑發生一個新的對象,所以a.add(b);固然做了加法操作,然則a並沒有保留加操作後的值,准確的用法應當是a=a.add(b);
5.總結
(1)貿易盤算應用BigDecimal。
(2)盡可能應用參數類型為String的結構函數。
(3) BigDecimal都是弗成變的(immutable)的,在停止每步運算時,都邑發生一個新的對象,所以在做加減乘除運算時萬萬要保留操作後的值。
(4)我們常常輕易疏忽JDK底層的一些完成細節,招致湧現毛病,須要多加留意。
參考:類 BigDecimal