浏览 373 次
|
该帖已经被评为新手帖
|
|
|---|---|
| 作者 | 正文 |
|
时间:2008-01-28 关键字: 关于数据的精确计算问题
关于数据的精确计算问题
在系统中如果设计他钱的问题必须精确计算.例如: 一个企业web call通话费用计算问题。每通话一次计算一次当前帐户余额.如果采用java基本数据类 型(int float double等)计算,模拟代码如下: /**
* 计算一次消费后的余额
* @param nowBalance 消费前的余额
* @param expenditure 本次消费金额
* @return
*/
public static double countBalance(double nowBalance,double expenditure){
return nowBalance-expenditure;
}这里如果nowBalance非常大假如是9999999999999999d,这时系统会按照科学计数法计算为1.0E16,但
是如果expenditure(本次消费金额)相对很小的时候模拟代码如下: double nowBalance=9999999999999999d; double expenditure=1d; double lastBalance=countBalance(nowBalance,1d);这时候lastBalance(消费后的余额)依然为1.0E16,不能精确计算是因为expenditure相对 nowBalance太小,但是如果该企业一天内进行了100000次通话消费每次消费的expenditure=1d,虚拟 代码: double nowBalance=9999999999999999d;
double expenditure=1d;
for(int i=1;i<=100000;i++){
lastBalance=countBalance(nowBalance,1d);
这时候lastBalance(消费后的余额)依然为1.0E16。 如果企业一次消费expenditure=100000d时候 double nowBalance=9999999999999999d; double expenditure=1d; double lastBalance=countBalance(nowBalance,100000d);这时候lastBalance(消费后的余额)依然为9.9999999999E15,也就是说采用这种基本java数据类 型计算的时候只要企业每次通话消费很小,都不会计算消费.显然采用这中计算方式是存在问题的. 如果要精确的解决比较的的数学计算问题最好采用java.math.BigDecimal来解决。 public static String countBalance(String nowBalance,String expenditure){
BigDecimal bigBalance = new BigDecimal(nowBalance);
BigDecimal bigMoney = new BigDecimal(expenditure);
DecimalFormat f = new DecimalFormat("#.00");
return f.format(bigBalance.subtract(bigMoney));
}
String nowBalance="9999999999999999";
double expenditure="1";
String lastBalance=countBalance(nowBalance,expenditure);这时lastBalance计算结果为9999999999999998.00.
我们伟大的测试部还发现一个很特别的问题,当采用float计算的时候 float d=Float.parseFloat("999999999999999999999999999999999999999999999999"); 此时d为Infinity,这种问题也只有测试他们才能发现。 任何一种语言的数据类型其实都存在溢出问题,而且在实际应用中基本数据类型就足够用,但是有 些时候测试的偏偏喜欢测试这种超出自然的数据。 声明:JavaEye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
|
|
| 返回顶楼 | |
|
时间:2008-01-28
这种东西发到入门。发这里会被扣分的。
|
|
| 返回顶楼 | |
|
时间:2008-01-28
嗯,入门级问题
|
|
| 返回顶楼 | |
|
时间:2008-01-29
诸如此类问题,请看effective java.
finally return 等问题,请看 java puzzler. |
|
| 返回顶楼 | |





