2008-01-28
开发中容易忽视的细节
关键字: 关于数据的精确计算问题
关于数据的精确计算问题
在系统中如果设计他钱的问题必须精确计算.例如:
一个企业web call通话费用计算问题。每通话一次计算一次当前帐户余额.如果采用java基本数据类
型(int float double等)计算,模拟代码如下:
是如果expenditure(本次消费金额)相对很小的时候模拟代码如下:
nowBalance太小,但是如果该企业一天内进行了100000次通话消费每次消费的expenditure=1d,虚拟
代码:
这时候lastBalance(消费后的余额)依然为1.0E16。
如果企业一次消费expenditure=100000d时候
型计算的时候只要企业每次通话消费很小,都不会计算消费.显然采用这中计算方式是存在问题的.
如果要精确的解决比较的的数学计算问题最好采用java.math.BigDecimal来解决。
我们伟大的测试部还发现一个很特别的问题,当采用float计算的时候
float d=Float.parseFloat("999999999999999999999999999999999999999999999999");
此时d为Infinity,这种问题也只有测试他们才能发现。
任何一种语言的数据类型其实都存在溢出问题,而且在实际应用中基本数据类型就足够用,但是有
些时候测试的偏偏喜欢测试这种超出自然的数据。
在系统中如果设计他钱的问题必须精确计算.例如:
一个企业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,这种问题也只有测试他们才能发现。
任何一种语言的数据类型其实都存在溢出问题,而且在实际应用中基本数据类型就足够用,但是有
些时候测试的偏偏喜欢测试这种超出自然的数据。
评论
Godlikeme
2008-01-29
诸如此类问题,请看effective java.
finally return 等问题,请看 java puzzler.
finally return 等问题,请看 java puzzler.
MarkDong
2008-01-28
嗯,入门级问题
魔力猫咪
2008-01-28
这种东西发到入门。发这里会被扣分的。
发表评论
提醒: 该博客已发表在公共论坛,博客所有留言会成为论坛回贴,留言请注意遵守论坛发贴规则
- 浏览: 16349 次
- 性别:

- 来自: 北京

- 详细资料
搜索本博客
最近加入圈子
最新评论
-
OA和ERP的区别
这完全是两个不同的方向!
-- by yangdefeng95802 -
实现梦想的才是最好的
引用~~~~庄子说:有一种活法叫做逍遥游!支持oo~~说得不错~~平淡简单的生活 ...
-- by joyandpaul -
实现梦想的才是最好的
@happycookie引用这个确实可是梦想在哪里?呵呵,梦想就是:你想要的生活 ...
-- by joyandpaul -
说几个自己知道的公司情况
.....
-- by mliz -
说几个自己知道的公司情况
acgzhang 写道@王贵伟 引用3.华美汉盛(ACG): 我老婆的公司,公司 ...
-- by lynn.wong






评论排行榜