new BigDecimal(0.01) 与 new BigDecimal(String.valueOf(0.01))的区别 (转)

时间:2023-03-09 21:26:22
new BigDecimal(0.01) 与 new BigDecimal(String.valueOf(0.01))的区别 (转)

转自:http://blog.****.net/major1985/article/details/50210293

一般我们使用BigDecimal进行比较精密的计算,我这里计算金额。注意使用double构造器的本质与String构造的本质,避免造成问题。

我这里出现的问题是金额总是多了0.01

问题出现在这段代码:

if(valueDiffDays > ){
logger.info("该账单{}需要缴纳{}天利息",loanBillLogDO.getBillSeqNo(),valueDiffDays);
interestAmt = repayAmt * interestDayRate * valueDiffDays;
loanBillLogDO.setInterestAmt(new BigDecimal(interestAmt).setScale(, RoundingMode.UP)); }

应该是0.80的总是变成0.81,进行断点调试发现interestAmt的值是0.8.

进行测试:

 @Test
public void testBigDecimalMode(){
double dayRate = 0.08;
double amt = ;
int diff = ; double interestAmt = amt*dayRate/*diff;
BigDecimal tInterestAmt = new BigDecimal(interestAmt).setScale( , RoundingMode.UP);
System.out.println(interestAmt);
System.out.println(tInterestAmt); BigDecimal a = new BigDecimal("0.8");
System.out.println(a.setScale(, RoundingMode.UP));
BigDecimal b = new BigDecimal(0.8);
System.out.println(b.setScale( , RoundingMode.UP));
// loanBillLogDO.setInterestAmt(new BigDecimal(interestAmt).setScale(2, RoundingMode.UP));
}

基本确定BigDecimal的double构造存在问题,String构造不存在问题。

api说明:

new BigDecimal(0.01) 与 new BigDecimal(String.valueOf(0.01))的区别 (转)

BigDecimal

public BigDecimal(String val)
将 BigDecimal 的字符串表示形式转换为 BigDecimal。字符串表示形式由可选符号 '+' ( '\u002B') 或 '-' ( '\u002D') 组成,后跟零或多个十进制数字(“整数”)的序列,可以选择后跟一个小数,也可以选择后跟一个指数。
该小数由小数点以及后跟的零或更多十进制数字组成。字符串必须至少包含整数或小数部分中的一个数字。由符号、整数和小数部分组成的数字称为有效位数。 指数由字符 'e'('\u0065') 或 'E' ('\u0045') 以及后跟的一个或多个十进制数字组成。指数的值必须位于 Integer.MAX_VALUE (Integer.MIN_VALUE+) 和 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 的任何字符,如 、、……
返回的 BigDecimal 的标度将是小数部分中的数字位数,如果该字符串不包含小数点,则标度为零,这取决于对指数的调整;如果字符串包含一个指数,则从标度减去该指数。得到的标度值必须位于 Integer.MIN_VALUE 和 Integer.MAX_VALUE(包括)之间。 Character.digit(char, int) 集提供从字符到数字的映射,以转换成基数 。该字符串不能包含任何额外字符(例如,空白)。 示例:
返回的 BigDecimal 的值等于有效位数 × 指数。对于左边的每个字符串,得到的表示形式 [BigInteger, scale] 显示在右边。 "" [,]
"0.00" [,]
"" [,]
"-123" [-,]
"1.23E3" [,-]
"1.23E+3" [,-]
"12.3E+7" [,-]
"12.0" [,]
"12.3" [,]
"0.00123" [,]
"-1.23E-12" [-,]
"1234.5E-4" [,]
"0E+7" [,-]
"-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))的区别 (转)