1 0

一个简答double计算在jrockit_150_22运行变成了17700478709.78,上亿的数值10

最近运到一个很棘手的问题,请大家帮我看看,就是一个简单double数值计算,在jdk下运行正常,但是是在jrockit下运行出的结果变成了上亿了。jrockit在linux redhat 5环境下运行,也不是每次都能报出该问题,有时候把shell启动参数设置小-server   -Xms20M -Xmx60M  就能重新改问题。

 <INFO> 88060051164011
 
<INFO> FineRate
 
INFO  2012-12-11 20:12:48 [cn.com.jbbis.common.cls.ClsCompute] [getPI] -  333   ClsConst.PI_INTE, +double Capi 58301.78, double thisRate 17.82, double thisTermRate  0.0, double thisIntePerc, 0.0
INFO  2012-12-11 20:12:48 [cn.com.jbbis.common.cls.ClsCompute] [getPI] -  337   ClsConst.PI_INTE, 1.770047870978E10  ClsConst.PI_S_ALLOINTE, 1.770047870978E10  ClsConst.PI_S_SUBSINTE, 1.770047870978E10
INFO  2012-12-11 20:12:48 [cn.com.jbbis.common.cls.ClsCompute] [getPI] -  415 ClsConst.PI_INTE, 1.770047870978E10  ClsConst.PI_S_ALLOINTE, 1.770047870978E10  ClsConst.PI_S_SUBSINTE, 1.770047870978E10
INFO  2012-12-11 20:12:48 [cn.com.jbbis.common.cls.ClsCompute] [getFine] - 285  raFine:1.770047870978E10
<INFO> 88060051164011

 

 

上面是我的运行日志,下面我把该处代码帖出来。

 

 

     这个twoTest方法我根据生产报错,把输入的值记录起来,重新传入的模拟写的一个测试方法。上面 - 337处打印的日志就是ClsComputeUtils.InteByDay2()方法返回的值。

    在sun jdk下运行正常, 但是在bea jrockit 下则运行有错误。该问题我总结大致出错有两种可能

 

  1. double 精确计算错误,导致值偏大。 
  2. 我在本地都是把启动内存 -Xms20M -Xmx60M  在重现出来,在cpu资源很卡的情况下。在生产服务器-Xms512M -Xmx1024M  都能重现,但是机器cpu mey都使用很厉害情况下。
  3. ClsPublic.DateDiff("d", EndDate, BeginDate) 这两个日期计算相差天数的在方法有错。在jrockit有错

  

      

 

 

    

 @Test
	public void twoTest(){
    	
    	for(int i=0;i<10000;i++){
    	
    	//  2009-12-21 0:00:00----------           2012-8-25 0:00:00
    	Date BeginDate=DateUtils.parserDate("2009-12-21", DateUtils.SHORT_DATE_FORMAT_STR);
		Date EndDate=DateUtils.parserDate("2012-8-25", DateUtils.SHORT_DATE_FORMAT_STR);
//    	ClsPublic.DateDiff("d", EndDate, BeginDate);
		double Capi= 58301.78,thisRate =17.82,thisIntePerc=0.0;
		

     try {
		double b=ClsComputeUtils.InteByDay2(BeginDate, EndDate, 58301.78, thisRate, thisIntePerc, ClsConst.RATE_INTERATE, ClsConst.COMP_KIND_S_INTE);
	
		logger.info("=============="+b);
     } catch (Exception e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}
     
    	}
     
     
	}

 

public static double InteByDay2(Date BeginDate, Date EndDate, double C,
			double Rate, double IntePerc, String FieldName, String strCompKind) throws Exception {

		double dblCalcRate = getCalcRate(Rate, IntePerc, strCompKind);
		double dblCalcRateOfDay = getCalcRateOfDay(FieldName, dblCalcRate);
		
		logger.info(" 504  dblCalcRate:"+C +"  dblCalcRateOfDay : "+dblCalcRateOfDay);
		
		
//		double b= C * ClsPublic.DateDiff("d", EndDate, BeginDate) * dblCalcRateOfDay;
		
//		logger.info(" 504  b:"+b );
		
//		return b;
		
		return  C * ClsPublic.DateDiff("d", EndDate, BeginDate) * dblCalcRateOfDay;

	}

     

 

 

 

 

 

private  static double getCalcRate(double InteRate, double IntePerc, String strCompKind) throws Exception {
		if(ClsConst.COMP_KIND_S_INTE.equalsIgnoreCase(strCompKind)){
			return InteRate;
		}else if (ClsConst.COMP_KIND_S_SUBSINTE.equalsIgnoreCase(strCompKind)){
			return InteRate * (1 - IntePerc / 100);
		}else if (ClsConst.COMP_KIND_S_ALLOINTE.equalsIgnoreCase(strCompKind)){
			return InteRate * IntePerc / 100;
		}else{
			throw new NullPointerException("Not_COMP_KIND_S");
		}
	}

 

 

 

private static double getCalcRateOfDay(String FieldName, double dblRate) throws Exception {
		if (FieldName.equalsIgnoreCase(ClsConst.RATE_INTERATE)) {
			return ClsRateDeal.getRateOfDay(dblRate);
		}else if (FieldName.equalsIgnoreCase(ClsConst.RATE_FINERATE)) {
			return ClsRateDeal.getFineRateOfDay(dblRate);
		}else {
			throw new NullPointerException("FieldNameNotFound");
		}
	}

 

/**
	 * 日期操作方法 返回两个日期的间隔,如果interval="d" 返回天数,如果interval="m" 返回月数,否则返回0
	 * <br><b>按照算头不算尾的原则计算</b></br>
	 * @param interval
	 * @param EndDate
	 * @param BeginDate
	 * @return
	 */
	public static int DateDiff(String interval, Date EndDate, Date BeginDate) {
		
		
		logger.info(" 685 EndDate:"+EndDate  +" BeginDate:"+BeginDate);
		
		int i = 0;
		Calendar cEnd = Calendar.getInstance();
		Calendar cBegin = Calendar.getInstance();
		cEnd.setTime(EndDate);
		cBegin.setTime(BeginDate);

		cEnd.set(Calendar.SECOND, 0);
		cEnd.set(Calendar.MINUTE, 0);
		cEnd.set(Calendar.HOUR_OF_DAY, 0);
		cBegin.set(Calendar.SECOND, 0);
		cBegin.set(Calendar.MINUTE, 0);
		cBegin.set(Calendar.HOUR_OF_DAY, 0);

		if ("d".equals(interval)) {
			
			long intev = cEnd.getTimeInMillis() - cBegin.getTimeInMillis();
			double dd = (intev / (1000.0D * 60.0D * 60.0D * 24.0D));
			i = (int) dd;
			if ((dd - (double) i) > 0.001D){
				i += 1;
			}
		} else if ("m".equals(interval)) {
			
			i = (cEnd.get(Calendar.YEAR) - cBegin.get(Calendar.YEAR)) * 12
					+ (cEnd.get(Calendar.MONTH) - cBegin.get(Calendar.MONTH));

			Date datDateTemp = DateAdd("m", i, BeginDate, 0);
			if (datDateTemp.before(EndDate)) {
				i = i + 1;
			}
		} else if ("y".equals(interval)) {
			
			return cEnd.get(Calendar.YEAR) - cBegin.get(Calendar.YEAR);
		} else {
			
			i = 0;
		}
		
		
		
		logger.info(" 727 时间天数 i:"+i);
		
		return i ;
	}

 

 

 

 

 


问题补充:有经常使用JRockit 来项目开发的朋友吗!
2012年12月20日 19:04

1个答案 按时间排序 按投票排序

0 0

引用
DateUtils.parserDate

这个方法的实现呢?
如果你用的是java.text.SimpleDateFormat会有并发同步问题:
引用
日期格式是不同步的。建议为每个线程创建独立的格式实例。如果多个线程同时访问一个格式,则它必须是外部同步的。


我想问题是因为多线程并发时出现的。

2012年12月21日 08:44

相关推荐

Global site tag (gtag.js) - Google Analytics