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

对于大值,速率公式未按预期工作

  • 在物理文件中返回0.05819488005的速率(85.77534246575343,-1589.0,-18664.0,5855586.0)

  • 如果我们试图通过POI设置的相同公式返回0.009056339275922086

  • 即使我们试图保存excel并打开返回的0.009056339275922086
  • 用于在POI中设置的代码:

    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