BigDecimal,金融货币计算中的关键技术
2006-09-09 17:27
531 查看
1) 在设计数据库的时候用float或double作为货币的数据类型。会发现当数据的小数位比较多时,算出的结果和计算器的结果并不一致而且当数据非常大时(>9999999.0) 就自动转化为科学记数法来表示。如System.out.println(999999999.1);输出结果为9.999999991E8。因此float型根本无法胜任有关货币的计算并且会产生致命的错误。
2) 在Sql Server联机帮助中这样写道:在 Transact-SQL 中,numeric与 decimal数据类型在功能上等效。当数据值一定要按照指定精确存储时,可以用带有小数的 decimal数据类型来存储数字。
Decimal带2个参数(p和s)
p(精度)
指定小数点左边和右边可以存储的十进制数字的最大个数。精度必须是从 1 到最大精度之间的值。最大精度为 38。
s(小数位数)
指定小数点右边可以存储的十进制数字的最大个数。小数位数必须是从 0 到 p 之间的值。默认小数位数是 0,因而 0 <= s <= p。最大存储大小基于精度而变化。
当结果精度大于 38 时,相应的小数位数会减少,以避免结果的整数部分被截断。
因此我们选用decimal为货币的数据类型。
3) 在《Effective Java》这本书中提到这个原则,float和double只能用来做科学计算或者是工程计算,在商业计算中我们要用java.math.BigDecimal。
因此在货币等对精度要求很高的计算中我们用BigDecimal。BigDecimal有4个构造函数,我们只关心其中的两个:
BigDecimal(double val)
Translates a double into a BigDecimal;
BigDecimal(String val)
Translates the String repre sentation of a BigDecimal into a BigDecimal.
在使用这两个构造函数的时候要特别注意,下面请看一个例子:
System.out.println(new java.math.BigDecimal(1.1));
System.out.println(new java.math.BigDecimal(String.valueOf(1.1)));
执行结果为:
1.100000000000000088817841970012523233890533447265625
1.1
由此可见,若需要非常精确的计算结果,必须使用String来构造BigDecimal。
下面用实例代码演示如何使用BigDecimal:
Connection con=DataBaseConnection.getConnection();
PreparedStatement pstmt=con.prepareStatement("insert inout (cjfpId,scqyName,cpName,guige,dw,inNumber,inCome,inAmount) values(?,?,?,?,?,?,?,?)");
pstmt.setString(1,cjfpId[i]);
pstmt.setString(2,trans(scqyName[i]));
pstmt.setString(3,trans(cpName[i]));
pstmt.setString(4,trans(guige[i]));
pstmt.setString(5,trans(dw[i]));
pstmt.setBigDecimal(6,new BigDecimal(String.valueOf(inNumber[i])));
pstmt.setBigDecimal(7,new BigDecimal(String.valueOf(inCome[i])));
pstmt.setBigDecimal(8,new BigDecimal(String.valueOf(inAmount)));
pstmt.executeUpdate();
4) 有时用BigDecimal也会遇到一些奇怪的问题,比如下面代码:
System.out.println(new java.math.BigDecimal(String.valueOf(0)).multiply(new
java.math.BigDecimal(String.valueOf(2.32))));
System.out.println(new ava.math.BigDecimal(String.valueOf(0.0)).multiply(new
java.math.BigDecimal(String.valueOf(2.32))));
执行结果为:
0.00
0.000
此时,若要比较两结果的值时若用equals()会认为两个值是相等的,此时可有两个方法来处理:compareTo()或者用if(a.doubleValue()==0.0)比较。
在涉及金融货币计算中需要特别精确。浮点数不是精确值,使用它们会导致计算结果和他们原来的计算结果不一致。因此,使用浮点数来试图表示象货币量这样的精确数量是不可行的。使用浮点数来进行金融计算会得到灾难性的后果。无任在C++还是Java等一些程序设计语言中浮点数计算都不怎么精确,因此浮点数不可表示货币类计算。
2) 在Sql Server联机帮助中这样写道:在 Transact-SQL 中,numeric与 decimal数据类型在功能上等效。当数据值一定要按照指定精确存储时,可以用带有小数的 decimal数据类型来存储数字。
Decimal带2个参数(p和s)
p(精度)
指定小数点左边和右边可以存储的十进制数字的最大个数。精度必须是从 1 到最大精度之间的值。最大精度为 38。
s(小数位数)
指定小数点右边可以存储的十进制数字的最大个数。小数位数必须是从 0 到 p 之间的值。默认小数位数是 0,因而 0 <= s <= p。最大存储大小基于精度而变化。
当结果精度大于 38 时,相应的小数位数会减少,以避免结果的整数部分被截断。
因此我们选用decimal为货币的数据类型。
3) 在《Effective Java》这本书中提到这个原则,float和double只能用来做科学计算或者是工程计算,在商业计算中我们要用java.math.BigDecimal。
因此在货币等对精度要求很高的计算中我们用BigDecimal。BigDecimal有4个构造函数,我们只关心其中的两个:
BigDecimal(double val)
Translates a double into a BigDecimal;
BigDecimal(String val)
Translates the String repre sentation of a BigDecimal into a BigDecimal.
在使用这两个构造函数的时候要特别注意,下面请看一个例子:
System.out.println(new java.math.BigDecimal(1.1));
System.out.println(new java.math.BigDecimal(String.valueOf(1.1)));
执行结果为:
1.100000000000000088817841970012523233890533447265625
1.1
由此可见,若需要非常精确的计算结果,必须使用String来构造BigDecimal。
下面用实例代码演示如何使用BigDecimal:
Connection con=DataBaseConnection.getConnection();
PreparedStatement pstmt=con.prepareStatement("insert inout (cjfpId,scqyName,cpName,guige,dw,inNumber,inCome,inAmount) values(?,?,?,?,?,?,?,?)");
pstmt.setString(1,cjfpId[i]);
pstmt.setString(2,trans(scqyName[i]));
pstmt.setString(3,trans(cpName[i]));
pstmt.setString(4,trans(guige[i]));
pstmt.setString(5,trans(dw[i]));
pstmt.setBigDecimal(6,new BigDecimal(String.valueOf(inNumber[i])));
pstmt.setBigDecimal(7,new BigDecimal(String.valueOf(inCome[i])));
pstmt.setBigDecimal(8,new BigDecimal(String.valueOf(inAmount)));
pstmt.executeUpdate();
4) 有时用BigDecimal也会遇到一些奇怪的问题,比如下面代码:
System.out.println(new java.math.BigDecimal(String.valueOf(0)).multiply(new
java.math.BigDecimal(String.valueOf(2.32))));
System.out.println(new ava.math.BigDecimal(String.valueOf(0.0)).multiply(new
java.math.BigDecimal(String.valueOf(2.32))));
执行结果为:
0.00
0.000
此时,若要比较两结果的值时若用equals()会认为两个值是相等的,此时可有两个方法来处理:compareTo()或者用if(a.doubleValue()==0.0)比较。
在涉及金融货币计算中需要特别精确。浮点数不是精确值,使用它们会导致计算结果和他们原来的计算结果不一致。因此,使用浮点数来试图表示象货币量这样的精确数量是不可行的。使用浮点数来进行金融计算会得到灾难性的后果。无任在C++还是Java等一些程序设计语言中浮点数计算都不怎么精确,因此浮点数不可表示货币类计算。
相关文章推荐
- 云计算:体系架构与关键技术
- 云计算与大数据系列:1分钟看懂弹性计算云EC2的关键技术
- 认知计算与区块链技术变革金融IT架构
- 数字货币与区块链关键技术(新浪分享PPT全文)
- 云计算的关键技术
- 货币计算中的精度问题--java.math.BigDecimal
- double计算,小数计算,BigDecimal计算,货币计算,float计算,浮点计算
- 两本云计算书籍光盘及源码分享:走进云计算和云计算的关键技术与应用实例
- 货币计算为什么使用BigDecimal
- 货币金额的计算 - Java中的BigDecimal
- 云计算:概念现状及关键技术
- 云计算发展进程中的六大关键技术
- 货币金额的计算 - Java中的BigDecimal
- Java金融货币计算探讨与实现
- 大数据流式计算:关键技术及系统实例
- 云计算的关键技术(虚拟-服务-数据)-整合平台
- 金融项目java开发_BigDecimal(解决计算精度问题)
- 云计算基础设施的构建方法及关键技术
- 大数据流式计算:关键技术及系统实例
- 神经形态计算技术有望成为智能无人系统的关键