2017-11-09 3 views
0

Rate Formel ist nicht für große Werte wie erwartet ...Apache POI Rate Formel funktioniert nicht, wenn die Daten große

  1. RATE (85,77534246575343, -1.589,0, -18.664,0, 5.855.586,0) in physische Datei kehrt 0,05819488005

  2. , wenn die gleiche Formel, die wir durch POI zu setzen versuchen ,009056339275922086 zurück ..

    1. Auch haben wir versucht, die Excel und öffnet gleiche ,009056339275922086 zurückgegeben zu speichern ..

-Code verwendet in POI einzustellen:

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(); 

Antwort

0

Die Rate Funktion von apache poi besagt, dass es "// root von Newton Sekantenverfahren finden". Das ist Unsinn, da Secant method nur eine Quasi-Newton-Methode ist. Und "If the initial values are not close enough to the root, then there is no guarantee that the secant method converges.".

So ist den Standard guess von 0.1 scheint nicht „nahe genug“ und so, wenn wir cell.setCellFormula("RATE(85.77534246575343, -1589.0, -18664.0, 5855586.0, 0, 0.06)"); verwenden - beachten Sie die explizite Einstellung von type und guess Eigenschaften und mit der guess Eigenschaft „nahe genug“, um das Ergebnis der 0.05819488005 - dann dem Formel wird richtig ausgewertet.

Wenn apache poi wirklich Newton's method verwenden würde, würde die Funktion auch mit dem Standard guess von 0.1 richtig ausgewertet werden. Der Nachteil des Newton-Verfahrens besteht darin, dass es die Bewertung von f und seiner Ableitung f′ bei jedem Schritt erfordert. Es kann also in manchen Fällen langsamer als die Secant-Methode sein.

Beispiel:

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(); 

} 

}