new BigDecimal(0.01) 與 new BigDecimal(String.valueOf(0.01))的區別 (轉)
阿新 • • 發佈:2017-05-16
賬單 rto sta egerp 存在 調整 nan com mod
轉自:http://blog.csdn.net/major1985/article/details/50210293
一般我們使用BigDecimal進行比較精密的計算,我這裏計算金額。註意使用double構造器的本質與String構造的本質,避免造成問題。
我這裏出現的問題是金額總是多了0.01
問題出現在這段代碼:
if(valueDiffDays > 0){ logger.info("該賬單{}需要繳納{}天利息",loanBillLogDO.getBillSeqNo(),valueDiffDays); interestAmt = repayAmt * interestDayRate * valueDiffDays; loanBillLogDO.setInterestAmt(new BigDecimal(interestAmt).setScale(2, RoundingMode.UP)); }
應該是0.80的總是變成0.81,進行斷點調試發現interestAmt的值是0.8.
進行測試:
@Test public void testBigDecimalMode(){ double dayRate = 0.08; double amt = 1000; int diff = 1; double interestAmt = amt*dayRate/100*diff; BigDecimal tInterestAmt= new BigDecimal(interestAmt).setScale(2 , RoundingMode.UP); System.out.println(interestAmt); System.out.println(tInterestAmt); BigDecimal a = new BigDecimal("0.8"); System.out.println(a.setScale(2, RoundingMode.UP)); BigDecimal b = new BigDecimal(0.8); System.out.println(b.setScale(2 , RoundingMode.UP)); // loanBillLogDO.setInterestAmt(new BigDecimal(interestAmt).setScale(2, RoundingMode.UP)); }
基本確定BigDecimal的double構造存在問題,String構造不存在問題。
api說明:
BigDecimal public BigDecimal(String val) 將 BigDecimal 的字符串表示形式轉換為 BigDecimal。字符串表示形式由可選符號 ‘+‘ ( ‘\u002B‘) 或 ‘-‘ ( ‘\u002D‘) 組成,後跟零或多個十進制數字(“整數”)的序列,可以選擇後跟一個小數,也可以選擇後跟一個指數。 該小數由小數點以及後跟的零或更多十進制數字組成。字符串必須至少包含整數或小數部分中的一個數字。由符號、整數和小數部分組成的數字稱為有效位數。 指數由字符 ‘e‘(‘\u0065‘) 或 ‘E‘ (‘\u0045‘) 以及後跟的一個或多個十進制數字組成。指數的值必須位於 Integer.MAX_VALUE (Integer.MIN_VALUE+1) 和 Integer.MAX_VALUE(包括)之間。 更正式地說,以下語法描述了此構造方法接受的字符串: BigDecimalString: Signopt Significand Exponentopt Sign: + - Significand: IntegerPart . FractionPartopt . FractionPart IntegerPart IntegerPart: Digits FractionPart: Digits Exponent: ExponentIndicator SignedInteger ExponentIndicator: e E SignedInteger: Signopt Digits Digits: Digit Digits Digit Digit: Character.isDigit(char) 對其返回 true 的任何字符,如 0、1、2…… 返回的 BigDecimal 的標度將是小數部分中的數字位數,如果該字符串不包含小數點,則標度為零,這取決於對指數的調整;如果字符串包含一個指數,則從標度減去該指數。得到的標度值必須位於 Integer.MIN_VALUE 和 Integer.MAX_VALUE(包括)之間。 Character.digit(char, int) 集提供從字符到數字的映射,以轉換成基數 10。該字符串不能包含任何額外字符(例如,空白)。 示例: 返回的 BigDecimal 的值等於有效位數 × 10 指數。對於左邊的每個字符串,得到的表示形式 [BigInteger, scale] 顯示在右邊。 "0" [0,0] "0.00" [0,2] "123" [123,0] "-123" [-123,0] "1.23E3" [123,-1] "1.23E+3" [123,-1] "12.3E+7" [123,-6] "12.0" [120,1] "12.3" [123,1] "0.00123" [123,5] "-1.23E-12" [-123,14] "1234.5E-4" [12345,5] "0E+7" [0,-7] "-0" [0,0] 註:對於不是 float、double NaN 和 ±Infinity 的值,此構造方法與 Float.toString(float) 和 Double.toString(double) 返回的值兼容。這通常是將 float 或 double 轉換為 BigDecimal 的首選方法,因為它不會遇到 BigDecimal(double) 構造方法的不可預知問題。 參數: val - BigDecimal 的字符串表示形式。 拋出: NumberFormatException - 如果 val 不是 BigDecimal 的有效表示形式。
new BigDecimal(0.01) 與 new BigDecimal(String.valueOf(0.01))的區別 (轉)