转自:http://blog.csdn.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说明:

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))的区别 (转)的更多相关文章

  1. String.valueOf()和toString()的区别

    1.String.valueOf(): Object obj=null; String str=""; str=String.valueOf(obj); //str=obj.toS ...

  2. 这种写法用过没:string.Format("{0,-10}", 8)

    1 2 3 4 var s1 = string.Format("{0,-10}", 8); var s2 = string.Format("{0,10}", 8 ...

  3. Java的String.valueOf 转换 与、空串+类型变量转换与封装类(Integer)的toString方式转换比较。

    1.空串+类型变量方式转换 int i=20; String s=""+i; 这种方式实际上经过了两个步骤,首先进行了i.ToString()把 i 转换为 字符串,然后再进行加法 ...

  4. try { var mergeFilePath = string.Format("{0}mergepdf.pdf", tempDownDir); PDFPrintHelper.MergePDFFile(pdfList, mergeFi

    winform 按顺序连续打印多个PDF文件   关于PDF打印的问题,前面有篇文章(点这里查看)也叙述过,今天来谈谈另外一种方法 其实方法很简单,因为需要把多个PDF文档按顺序连续打印,为此我们为什 ...

  5. case a.ass_term_unit when '01' then (case a.ass_profit_mode when '0' then round(sum(a.ass_amount*a.ass_annual_rate/365*365*a.ass_term/100) ,2) when '1' then round(sum(a.ass_amount*a.ass_annual_rate/

    --01 年 02 月 03 日 select a.ass_due_date, case a.ass_term_unit when '01' then (case a.ass_profit_mode ...

  6. Java中string.equalsIgnoreCase("0")与"0".equalsIgnoreCase(string)的区别:

    string.equalsIgnoreCase("0"):如果string为null,会抛出java.lang.NullPointerException异常. "0&qu ...

  7. tensorflow models api:ValueError: Tensor conversion requested dtype string for Tensor with dtype float32: 'Tensor("arg0:0", shape=(), dtype=float32, device=/device:CPU:0)'

    tensorflow models api:ValueError: Tensor conversion requested dtype string for Tensor with dtype flo ...

  8. org.apache.tomcat.util.descriptor.web.WebXml.setVersion Unknown version string [4.0]. Default version will be used.报错

    org.apache.tomcat.util.descriptor.web.WebXml.setVersion Unknown version string [4.0]. Default versio ...

  9. YII报错笔记:<pre>PHP Notice &#039;yii\base\ErrorException&#039; with message &#039;Uninitialized string offset: 0&#039; in /my/test/project/iot/vendor/yiisoft/yii2/base/Model.php:778

    YII常见报错笔记 报错返回的代码如下: <pre>PHP Notice 'yii\base\ErrorException' with message 'Uninitialized str ...

随机推荐

  1. spring自定义事务同步器(二):借助redisson实现自己的同步器

    1. 借助redis的java客户端redisson实现自己的事物同步器 @Override public void lockWithinCurrentTransaction(Object key) ...

  2. shell 环境变量的知识小结

    环境变量的知识小结:·变量名通常要大写.·变量可以在自身的Shell及子Shell中使用.·常用export来定义环境变量.·执行env默认可以显示所有的环境变量名称及对应的值.·输出时用“$变量名” ...

  3. redis.conf配置文件说明

    # Redis 配置文件 # 当配置中需要配置内存大小时,可以使用 1k, 5GB, 4M 等类似的格式,其转换方式如下(不区分大小写) # # 1k => 1000 bytes # 1kb = ...

  4. The adidas NMD Singapore is one of the brands top selling

    Like pointed out, we've two adidas NMD Singapore releases using the first arriving Blue and Black as ...

  5. 问题:ORA-28000: the account is locked 用户锁住了。

    打开cmd: 执行 sqlplus /nolog 执行conn / as sysdba 执行 ALTER USER  username  ACCOUNT UNLOCK;

  6. try with resources简洁的异常捕获机制

    通过前篇的<Java文件IO流的操作总结>,我们知道了基本输入输出流的使用方式,但是每次都需要在finally处关闭流资源,这样操作起来既啰嗦又麻烦,有没有更简洁的方式呢?本篇就来讲解jd ...

  7. 1linux的基本命令

    查看命令的帮助信息man 命令名 文件操作touch 建立文件 (对于已存在文件,更新时间)cat 查看文件 (-n 自动加上行号)rm 删除文件cp 拷贝文件mv 移动/重命名文件more 分页查看 ...

  8. Learning to Rank之RankNet算法简介

    排序一直是信息检索的核心问题之一, Learning to Rank(简称LTR)用机器学习的思想来解决排序问题(关于Learning to Rank的简介请见我的博文Learning to Rank ...

  9. CV 两幅图像配准

    http://www.cnblogs.com/Lemon-Li/p/3504717.html 图像配准算法一般可分为: 一.基于图像灰度统计特性配准算法:二.基于图像特征配准算法:三.基于图像理解的配 ...

  10. ExtJS实现分页grid paging

    背景 分页查询在Web页面中比例很大,我自己也写过分页框架,也用过很多第三方分页. 基于jquery的dataTables,那么多例子.清晰API.应用广泛.开源,即使是新手也可以很快上手. ExtJ ...