Java Apache POI速率公式与长周期不一致
为了模拟Excel的rate函数,我使用了从svn获取的rate函数:Java Apache POI速率公式与长周期不一致,java,apache-poi,Java,Apache Poi,为了模拟Excel的rate函数,我使用了从svn获取的rate函数: 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_ITERATION
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) {
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 = pv + pmt * nper + fv;
y1 = pv * f + pmt * (1 / rate + type) * (f - 1) + fv;
// Find root by the Newton secant method
i = x0 = 0.0;
x1 = rate;
while ((Math.abs(y0 - y1) > 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;
在Excel中,我得到0.580,程序返回-1.1500428517726355。有什么提示吗?您在问题中粘贴的这段代码有很多错误 它假定始终找到一个速率(不为true),并且不为找不到速率的实例做准备 有些语句会抛出一个错误,使用更合适的编程语句可以避免这个错误。例如,从代码中提取以下语句:
f = Math.exp(nper * Math.log(1 + rate));
这将在尝试查找负值或零值的日志时引发错误。它本可以改写为
f = Math.pow(1 + rate, nper);
迭代计算中的注释指出,它正在编程,但会检查迭代计算是否收敛于错误的变量。当它应该测试利率的收敛性时,它正在测试未来价值的收敛性
我在记事本中复制粘贴了您的代码,删除了Java的变量声明,并将其替换为JavaScript变量声明,以使用示例数据测试代码。正如我所说的,代码在第二次迭代时停止,因为未来值的差值超出了误差范围,并且因为没有测试来确定是否找到了利率,代码返回的是正确的利率和错误的利率
我不知道为什么这段代码会在报告正确率的情况下工作,就像第一个数据集的情况一样。我建议以正确的方式重新编码函数。公共双费率(双nper、双pmt、双pv)
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;
}
{
//系统输出打印项次(“功能速率:+nper+”+pmt+“pv”+pv);
双误=0.0000001;
双高=1.00;
双低=0.00;
双费率=(2.0*(净现值*净现值-净现值))/(净现值*净现值);
while(true){
//检查误差幅度
双计算=数学功率(1+速率,nper);
计算值=(比率*计算值)/(计算值-1.0);
calc-=pmt/pv;
如果(计算>错误){
//猜测太高,请降低猜测
高=比率;
比率=(高+低)/2;
}
否则如果(计算<-错误){
//猜得太低,猜得越高。
低=比率;
比率=(高+低)/2;
}
否则{
//可接受的猜测
打破
}
}
//系统输出打印项次(“费率:+费率);
回报率;
}
示例:
=RATE(60211250065000000)
返回0.025198;Excel也一样(正确)。在Apache POI项目中打开错误报告,或搜索他们的错误数据库,看看这是否是一个已知的问题。看起来OP采纳了错误报告建议-刚刚在项目中提出感谢您的回答。在哪里可以找到公式或伪代码,以便我可以自己用java编写?
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;
}