您的位置:首页 > 其它

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等一些程序设计语言中浮点数计算都不怎么精确,因此浮点数不可表示货币类计算。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: