Function 如果数据较大,Apache POI速率公式不起作用
对于大值,速率公式未按预期工作Function 如果数据较大,Apache POI速率公式不起作用,function,apache-poi,rate,Function,Apache Poi,Rate,对于大值,速率公式未按预期工作 在物理文件中返回0.05819488005的速率(85.77534246575343,-1589.0,-18664.0,5855586.0) 如果我们试图通过POI设置的相同公式返回0.009056339275922086 即使我们试图保存excel并打开返回的0.009056339275922086 用于在POI中设置的代码: XSSFWorkbook workbook = new XSSFWorkbook(); XSSFRow row = sheet.c
XSSFWorkbook workbook = new XSSFWorkbook();
XSSFRow row = sheet.createRow(1);
XSSFCell cell = row.createCell(1);
cell.setCellType(CellType.NUMERIC);
cell.setCellFormula("RATE(85.77534246575343, -1589.0, -18664.0, 5855586.0)");
FormulaEvaluator evaluator = workbook.getCreationHelper().createFormulaEvaluator();
evaluator.evaluateInCell(cell);
cell.getNumericCellValue();
apachepoi
的函数声明它“//find root by Newton割线法”。这是胡说八道,因为它只是一个拟牛顿法。及”
因此0.1
的默认guess
似乎不够“接近”,如果我们使用cell.setCellFormula(“RATE(85.77534246575343,-1589.0,-18664.0,5855586.0,0,0.06)”代码>-注意类型
和猜测
属性的显式设置,并使猜测
属性与0.05819488005
的结果“足够接近”-然后公式正确计算
如果apachepoi确实要使用0.1
的默认值guess
,那么函数也会正确计算。牛顿方法的缺点是,它需要在每一步计算f
及其导数f′
。因此,在某些情况下,它可能比割线法慢
例如:
import java.io.FileOutputStream;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFSheet;
public class ExcelRATEFunction {
private static double calculateRateNewton(double nper, double pmt, double pv, double fv, double type, double guess) {
int FINANCIAL_MAX_ITERATIONS = 20;
double FINANCIAL_PRECISION = 0.0000001;
double y, y1, xN = 0, f = 0, i = 0;
double rate = guess;
//find root by Newtons method (https://en.wikipedia.org/wiki/Newton%27s_method), not secant method!
//Formula see: https://wiki.openoffice.org/wiki/Documentation/How_Tos/Calc:_Derivation_of_Financial_Formulas#PV.2C_FV.2C_PMT.2C_NPER.2C_RATE
f = Math.pow(1 + rate, nper);
y = pv * f + pmt * ((f - 1) / rate) * (1 + rate * type) + fv;
//first derivative:
//y1 = (pmt * nper * type * Math.pow(rate,2) * f - pmt * f - pmt * rate * f + pmt * nper * rate * f + pmt * rate + pmt + nper * pv * Math.pow(rate,2) * f) / (Math.pow(rate,2) * (rate+1));
y1 = (f * ((pmt * nper * type + nper * pv) * Math.pow(rate,2) + (pmt * nper - pmt) * rate - pmt) + pmt * rate + pmt) / (Math.pow(rate,3) + Math.pow(rate,2));
xN = rate - y/y1;
while ((Math.abs(rate - xN) > FINANCIAL_PRECISION) && (i < FINANCIAL_MAX_ITERATIONS)) {
rate = xN;
f = Math.pow(1 + rate, nper);
y = pv * f + pmt * ((f - 1) / rate) * (1 + rate * type) + fv;
//first derivative:
//y1 = (pmt * nper * type * Math.pow(rate,2) * f - pmt * f - pmt * rate * f + pmt * nper * rate * f + pmt * rate + pmt + nper * pv * Math.pow(rate,2) * f) / (Math.pow(rate,2) * (rate+1));
y1 = (f * ((pmt * nper * type + nper * pv) * Math.pow(rate,2) + (pmt * nper - pmt) * rate - pmt) + pmt * rate + pmt) / (Math.pow(rate,3) + Math.pow(rate,2));
xN = rate - y/y1;
++i;
System.out.println(rate+", "+xN+", "+y+", "+y1);
}
rate = xN;
return rate;
}
public static void main(String[] args) throws Exception {
Workbook workbook = new XSSFWorkbook();
Sheet sheet = workbook.createSheet();
Row row = sheet.createRow(1);
Cell cell = row.createCell(1);
cell.setCellFormula("RATE(85.77534246575343, -1589.0, -18664.0, 5855586.0, 0, 0.06)");
FormulaEvaluator evaluator = workbook.getCreationHelper().createFormulaEvaluator();
CellType celltype = evaluator.evaluateFormulaCellEnum(cell);
double value = 0.0;
if (celltype == CellType.NUMERIC) {
value = cell.getNumericCellValue();
System.out.println(value);
}
workbook.setForceFormulaRecalculation(true);
value = calculateRateNewton(85.77534246575343, -1589.0, -18664.0, 5855586.0, 0, 0.1);
System.out.println(value);
workbook.write(new FileOutputStream("ExcelRATEFunction.xlsx"));
workbook.close();
}
}
import java.io.FileOutputStream;
导入org.apache.poi.ss.usermodel.*;
导入org.apache.poi.xssf.usermodel.xssf工作簿;
导入org.apache.poi.xssf.usermodel.xssfheet;
公共类函数{
私人静态双计算牛顿(双nper、双pmt、双pv、双fv、双类型、双猜测){
int FINANCIAL_MAX_迭代次数=20;
双财务单位精度=0.0000001;
双y,y1,xN=0,f=0,i=0;
双速率=猜测;
//牛顿求根法(https://en.wikipedia.org/wiki/Newton%27s_method),不是割线法!
//公式见:https://wiki.openoffice.org/wiki/Documentation/How_Tos/Calc:_Derivation_of_Financial_Formulas#PV.2C_FV.2C_PMT.2C_NPER.2C_RATE
f=数学功率(1+速率,nper);
y=pv*f+pmt*((f-1)/费率)*(1+费率*类型)+fv;
//一阶导数:
//y1=(pmt*nper*类型*数学功率(速率,2)*f-pmt*f-pmt*速率*f+pmt*nper*速率*f+pmt*速率+pmt+nper*pv*数学功率(速率,2)*f)/(数学功率(速率,2)*(速率+1));
y1=(f*((pmt*nper*类型+nper*pv)*数学功率(比率,2)+(pmt*nper-pmt)*比率-pmt)+pmt*比率+pmt)/(数学功率(比率,3)+数学功率(比率,2));
xN=速率-y/y1;
而((Math.abs(rate-xN)>金融精度)和(&(i