Apache POI率公式与长期不一致

为了模拟Excel的速率函数,我使用了从svn中获取的Apache POI速率函数:

private double calculateRate(double nper, double pmt, double pv, double fv, double type, double guess) { //FROM MS http://office.microsoft.com/en-us/excel-help/rate-HP005209232.aspx int FINANCIAL_MAX_ITERATIONS = 20; //Bet accuracy with 128 double FINANCIAL_PRECISION = 0.0000001; //1.0e-8 double y, y0, y1, x0, x1 = 0, f = 0, i = 0; double rate = guess; if (Math.abs(rate)  FINANCIAL_PRECISION) && (i < FINANCIAL_MAX_ITERATIONS)) { rate = (y1 * x0 - y0 * x1) / (y1 - y0); x0 = x1; x1 = rate; if (Math.abs(rate) < FINANCIAL_PRECISION) { y = pv * (1 + nper * rate) + pmt * (1 + rate * type) * nper + fv; } else { f = Math.exp(nper * Math.log(1 + rate)); y = pv * f + pmt * (1 / rate + type) * (f - 1) + fv; } y0 = y1; y1 = y; ++i; } return rate; 

}

对于calculateRate(120,28.1,-2400,0,0,0.1)),输出与Excel相同: 0.599

但如果我尝试相同的计算,这次使用的值:

 calculateRate(360, 15.9, -2400, 0, 0, 0.1)) 

在Excel中我得到0.580 ,程序返回-1.1500428517726355 。 任何提示?

您在问题中粘贴了这段代码有很多错误。

它假定始终找到一个速率(不是真的),并且在没有找到速率时不对实例进行规定。

某些语句会抛出一个错误,可以通过使用更合适的编程语句来避免这种错误。 例如,从您的代码中获取以下语句:

 f = Math.exp(nper * Math.log(1 + rate)); 

尝试查找负值或零值的日志时,这将引发错误。 它可以被重写为

 f = Math.pow(1 + rate, nper); 

迭代计算中的注释表明它正在编写割线方法 ,但检查迭代计算是否存在错误变量的收敛。 当它应该测试利率的收敛时,它正在测试未来价值的收敛性。

我复制在记事本中粘贴您的代码并删除Java的变量声明,并用JavaScript变量声明替换它们以使用您的示例数据测试代码。 就像我说的那样,代码在第二次迭代时停止,因为未来值的差异超出了误差范围,并且因为没有测试来查看是否找到了一个速率,所以代码按原样返回利率这是错的。

我不确定为什么这个代码在报告正确速率的情况下工作,就像第一个数据集的情况一样。 我建议以正确的方式重新编码函数。

 public double rate(double nper, double pmt, double pv) { //System.out.println("function rate : " + nper + " " + pmt + " pv " + pv); double error = 0.0000001; double high = 1.00; double low = 0.00; double rate = (2.0 * (nper * pmt - pv)) / (pv * nper); while(true) { // Check for error margin double calc = Math.pow(1 + rate, nper); calc = (rate * calc) / (calc - 1.0); calc -= pmt / pv; if (calc > error) { // Guess is too high, lower the guess high = rate; rate = (high + low) / 2; } else if (calc < -error) { // Guess is too low, higher the guess. low = rate; rate = (high + low) / 2; } else { // Acceptable guess break; } } //System.out.println("Rate : " + rate); return rate; } 

示例: =RATE(60, 2112500, 65000000)返回0.025198; 与Excel相同(正确)。