论坛首页 入门讨论版

开发中容易忽视的细节

浏览 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,这种问题也只有测试他们才能发现。
任何一种语言的数据类型其实都存在溢出问题,而且在实际应用中基本数据类型就足够用,但是有

些时候测试的偏偏喜欢测试这种超出自然的数据。
   
时间:2008-01-28
这种东西发到入门。发这里会被扣分的。
   
0 请登录后投票
时间:2008-01-28
嗯,入门级问题
   
0 请登录后投票
时间:2008-01-29
诸如此类问题,请看effective java.
finally return 等问题,请看 java puzzler.
   
0 请登录后投票
论坛首页 入门讨论版

跳转论坛: