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

转自: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 的有效表示形式。

时间: 2024-08-29 16:21:18

new BigDecimal(0.01) 与 new BigDecimal(String.valueOf(0.01))的区别 (转)的相关文章

配置Mysql Cluster时出错Unable to connect with connect string: nodeid=0,localhost:1186问题的解决

在执行 /etc/init.d/ndbd --initial出现下列错误 [[email protected] ~]# /etc/init.d/ndbd --initialUnable to connect with connect string: nodeid=0,localhost:1186Retrying every 5 seconds. Attempts left: 12 11 10 9 8 7 6 5 4 3 2 1, failed. 解决办法 1.查看/etc/my.cnf文件配置

string.Format("{0,-50}", "qqqqqqqqqqqq")

//sss={"100"}.有两个花括号 string sss = string.Format("{{\"100\"}}", 100); //string.Format("{0,向(正为右,负为左)对齐的字符串长度}","展示的字符串"); string s = string.Format("{0,-50}", "qqqqqqqqqqqq")+string.Forma

PTC.Mathcad.Prime.5.0.0.0.Win64 +RAM Connection CONNECT Edition 12.00.01.40

Truth.Concepts.v2.00.0.59 1CD Cadence Allegro and OrCAD 17.20.000-2016 HF045 Update 1DVDCadence Allegro系统互连平台能够跨集成电路.封装和PCB协同设计高性能互连.应用平台的协同设计 方法,工程师可以迅速优化I/O缓冲器之间和跨集成电路.封装和PCB的系统互联.该方法能避免硬件返 工并降低硬件成本和缩短设计周期.约束驱动的Allegro流程包括高级功能用于设计捕捉.信号完整性和 物理实现.由于它

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 float32: 'Tensor("arg0:0", shape=(), dtype=float32, device=/device:CPU:0)' 这个原因是你的tf-record有问题哈.检查pipline里面的tfrecord. tensorflow models api:ValueErr

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

错误: 在 IDEA 创建WEB项目之后,打印出的日志中总是出现一行警告信息: 12-May-2018 15:52:30.692 警告 [RMI TCP Connection(3)-127.0.0.1] org.apache.tomcat.util.descriptor.web.WebXml.setVersion Unknown version string [4.0].Default version will be used. 原因: 当前Tomcat8.5不支持Web4.0版本,那要么降低W

linux命令:raid学习 raid 0 raid 1 raid 5 raid 10 raid 01

     raid简介: RAID(Redundant Array of Inexpensive Disks)称为廉价磁盘冗余阵列.RAID 的基本原理是把多个便宜的小磁盘 RAID级别介绍;一般常用的RAID阶层,分别是RAID 0.RAID1.RAID 2.RAID 3.RAID 4以及RAID 5,再加上二合一型 RAID 0+1或RAID 1+0﹝或称RAID 10﹞.我们先把这些RAID级别的优.缺点做个比较: RAID级别 相对优点 相对缺点RAID 0 存取速度最快 没有容错  

日期格式化{0:yyyy-MM-dd HH:mm:ss.fff}和{0:yyyy-MM-dd hh:mm:ss.fff}的区别

日期格式化{0:yyyy-MM-dd HH:mm:ss.fff}和{0:yyyy-MM-dd hh:mm:ss.fff}的区别 {0:yyyy-MM-dd HH:mm:ss.fff}:使用24小时制格式化日期{0:yyyy-MM-dd hh:mm:ss.fff}:使用12小时制格式化日期 以下同理,从左至右分别为-年-月-日 时:分:秒.毫秒{0:yyyy-MM-dd HH:mm:ss zzz}{0:yyyy-MM-dd HH:mm:ss.ff zzz}{0:yyyy-MM-dd HH:mm:s

11.2.0.4手动升级到12.1.0.2

1.手动升级前工作(1).备份数据库(2).运行pre-upgrade information tool(如果是使用DBUA升级,会自动执行该脚本工具) $ cd /u01/app/oracle12/product/12.1.0/dbhome_1/rdbms/admin $ sqlplus '/as sysdba' SQL*Plus: Release 11.2.0.4.0 Production on Thu Aug 6 08:26:57 2015 Copyright (c) 1982, 2013

【Java】String,StringBuffer与StringBuilder的区别??

String 字符串常量StringBuffer 字符串变量(线程安全)StringBuilder 字符串变量(非线程安全) 简要的说, String 类型和 StringBuffer 类型的主要性能区别其实在于 String 是不可变的对象, 因此在每次对 String 类型进行改变的时候其实都等同于生成了一个新的 String 对象,然后将指针指向新的 String 对象,所以经常改变内容的字符串最好不要用 String ,因为每次生成对象都会对系统性能产生影响,特别当内存中无引用对象多了以