View | Details | Raw Unified | Return to bug 50409
Collapse All | Expand All

(-)src/java/org/apache/poi/ss/formula/eval/FunctionEval.java (+1 lines)
Lines 100-105 Link Here
100
		retval[58] = FinanceFunction.NPER;
100
		retval[58] = FinanceFunction.NPER;
101
		retval[59] = FinanceFunction.PMT;
101
		retval[59] = FinanceFunction.PMT;
102
102
103
		retval[62] = new Irr();
103
		retval[63] = NumericFunction.RAND;
104
		retval[63] = NumericFunction.RAND;
104
		retval[64] = new Match();
105
		retval[64] = new Match();
105
		retval[65] = DateFunc.instance;
106
		retval[65] = DateFunc.instance;
(-)src/java/org/apache/poi/ss/formula/functions/Irr.java (+111 lines)
Line 0 Link Here
1
/* ====================================================================
2
   Licensed to the Apache Software Foundation (ASF) under one or more
3
   contributor license agreements.  See the NOTICE file distributed with
4
   this work for additional information regarding copyright ownership.
5
   The ASF licenses this file to You under the Apache License, Version 2.0
6
   (the "License"); you may not use this file except in compliance with
7
   the License.  You may obtain a copy of the License at
8
9
       http://www.apache.org/licenses/LICENSE-2.0
10
11
   Unless required by applicable law or agreed to in writing, software
12
   distributed under the License is distributed on an "AS IS" BASIS,
13
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
   See the License for the specific language governing permissions and
15
   limitations under the License.
16
==================================================================== */
17
18
package org.apache.poi.ss.formula.functions;
19
20
import org.apache.poi.ss.formula.TwoDEval;
21
import org.apache.poi.ss.formula.eval.ErrorEval;
22
import org.apache.poi.ss.formula.eval.NumberEval;
23
import org.apache.poi.ss.formula.eval.ValueEval;
24
25
/**
26
 * Calculates the internal rate of return.
27
 *
28
 * Syntax is IRR(values) or IRR(values,guess)
29
 *
30
 * @author Marcel May
31
 * @see <a href="http://en.wikipedia.org/wiki/Internal_rate_of_return#Numerical_solution">Wikipedia on IRR</a>
32
 * @see <a href="http://office.microsoft.com/en-us/excel-help/irr-HP005209146.aspx">Excel IRR</a>
33
 */
34
public final class Irr implements Function {
35
36
    public ValueEval evaluate(final ValueEval[] args, final int srcRowIndex, final int srcColumnIndex) {
37
        if (args.length == 1 && args[0] instanceof TwoDEval) {
38
            // Use default estimate
39
            double[] numbers = extractNumbers((TwoDEval) args[0]);
40
            return new NumberEval( irr(numbers));
41
        } else if (args.length == 2  && args[0] instanceof TwoDEval && args[1] instanceof NumberEval ) {
42
            double[] numbers = extractNumbers((TwoDEval) args[0]);
43
            return new NumberEval( irr(numbers, extractDouble(args[1])));
44
        } else {
45
            // Wrong number of arguments
46
            return ErrorEval.NA;
47
        }
48
    }
49
50
    private double[] extractNumbers(final TwoDEval pArg) {
51
        // Validate
52
        if (!pArg.isColumn() && !pArg.isRow()) {
53
            throw new RuntimeException("area" + pArg.getWidth() + "x" + pArg.getHeight() + " must be either row or column");
54
        }
55
        double[] res = new double[Math.max(pArg.getHeight(), pArg.getWidth())];
56
        if (pArg.isRow()) {
57
            for (int i = 0; i < res.length; i++) {
58
                res[i] = extractDouble(pArg.getValue(i, 0));
59
            }
60
        } else {
61
            for (int i = 0; i < res.length; i++) {
62
                res[i] = extractDouble(pArg.getValue(0, i));
63
            }
64
        }
65
        return res;
66
    }
67
68
    private double extractDouble(final ValueEval pValue) {
69
        if (pValue instanceof NumberEval) {
70
            return ((NumberEval) pValue).getNumberValue();
71
        }
72
        throw new RuntimeException("Can not convert to number: " + pValue);
73
    }
74
75
76
    /**
77
     * Computes the internal rate of return using an estimated irr of 10 percent.
78
     *
79
     * @param income the income values.
80
     * @return the irr.
81
     */
82
    public static double irr(double[] income) {
83
        return irr(income, 0.1d);
84
    }
85
86
    /**
87
     * Computes the internal rate of return using an estimated irr.
88
     *
89
     * @param income       the income values.
90
     * @param estimatedIrr the optional estimated irr.
91
     * @return the irr.
92
     * @see {http://en.wikipedia.org/wiki/Internal_rate_of_return#Numerical_solution}
93
     */
94
    public static double irr(double[] income, double estimatedIrr) {
95
        double r_prev = estimatedIrr / 2d;
96
        double npv_prev = FinanceLib.npv(r_prev, income);
97
        double r = estimatedIrr;
98
99
        // Stop iteration by iteration count or delta
100
        int iter = 0;
101
        while (Math.abs(r - r_prev) > 0.00001d && iter <= 20) {
102
            double npv =  FinanceLib.npv(r, income);
103
            double old_r = r;
104
            r -= npv * (r - r_prev) / (npv - npv_prev);
105
            npv_prev = npv;
106
            r_prev = old_r;
107
            iter++;
108
        }
109
        return r;
110
    }
111
}
0
  + text/plain
112
  + text/plain
1
  + Date Revision
113
  + Date Revision
2
  + native
114
  + native
(-)src/testcases/org/apache/poi/ss/formula/functions/TestIrr.java (+69 lines)
Line 0 Link Here
1
/* ====================================================================
2
   Licensed to the Apache Software Foundation (ASF) under one or more
3
   contributor license agreements.  See the NOTICE file distributed with
4
   this work for additional information regarding copyright ownership.
5
   The ASF licenses this file to You under the Apache License, Version 2.0
6
   (the "License"); you may not use this file except in compliance with
7
   the License.  You may obtain a copy of the License at
8
9
       http://www.apache.org/licenses/LICENSE-2.0
10
11
   Unless required by applicable law or agreed to in writing, software
12
   distributed under the License is distributed on an "AS IS" BASIS,
13
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
   See the License for the specific language governing permissions and
15
   limitations under the License.
16
==================================================================== */
17
18
package org.apache.poi.ss.formula.functions;
19
20
import junit.framework.TestCase;
21
import org.apache.poi.hssf.usermodel.*;
22
23
/**
24
 * Tests for {@link Irr}
25
 *
26
 * @author Marcel May
27
 */
28
public final class TestIrr extends TestCase {
29
30
    public void testIrr() {
31
        // http://en.wikipedia.org/wiki/Internal_rate_of_return#Example
32
        double[] incomes = {-4000d, 1200d, 1410d, 1875d, 1050d};
33
        double irr = Irr.irr(incomes);
34
        double irrRounded = Math.round(irr * 1000d) / 1000d;
35
        assertEquals("irr", 0.143d, irrRounded);
36
37
        // http://www.techonthenet.com/excel/formulas/irr.php
38
        incomes = new double[]{-7500d, 3000d, 5000d, 1200d, 4000d};
39
        irr = Irr.irr(incomes);
40
        irrRounded = Math.round(irr * 100d) / 100d;
41
        assertEquals("irr", 0.28d, irrRounded);
42
43
        incomes = new double[]{-10000d, 3400d, 6500d, 1000d};
44
        irr = Irr.irr(incomes);
45
        irrRounded = Math.round(irr * 100d) / 100d;
46
        assertEquals("irr", 0.05, irrRounded);
47
    }
48
49
    public void testEvaluateInSheet() {
50
        HSSFWorkbook wb = new HSSFWorkbook();
51
        HSSFSheet sheet = wb.createSheet("Sheet1");
52
        HSSFRow row = sheet.createRow(0);
53
54
        row.createCell(0).setCellValue(-4000d);
55
        row.createCell(1).setCellValue(1200d);
56
        row.createCell(2).setCellValue(1410d);
57
        row.createCell(3).setCellValue(1875d);
58
        row.createCell(4).setCellValue(1050d);
59
60
        HSSFCell cell = row.createCell(5);
61
        cell.setCellFormula("IRR(A1:A5)");
62
63
        HSSFFormulaEvaluator fe = new HSSFFormulaEvaluator(wb);
64
        fe.clearAllCachedResultValues();
65
        fe.evaluateFormulaCell(cell);
66
        double res = cell.getNumericCellValue();
67
        assertEquals(0.143d, Math.round(res * 1000d) / 1000d);
68
    }
69
}
0
  + text/plain
70
  + text/plain
1
  + Date Revision
71
  + Date Revision
2
  + native
72
  + native

Return to bug 50409