github-32: speed up Irr() Excel formula computation by replacing Math.pow() with multiplication. Thanks to Daniel Kuan! This closes #32.

https://github.com/apache/poi/pull/32

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1795266 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Javen O'Neal 2017-05-16 03:18:17 +00:00
parent be5106a1d7
commit b6f78f8d57

View File

@ -24,9 +24,6 @@ import org.apache.poi.ss.formula.eval.*;
* *
* Syntax is IRR(values) or IRR(values,guess) * Syntax is IRR(values) or IRR(values,guess)
* *
* @author Marcel May
* @author Yegor Kozlov
*
* @see <a href="http://en.wikipedia.org/wiki/Internal_rate_of_return#Numerical_solution">Wikipedia on IRR</a> * @see <a href="http://en.wikipedia.org/wiki/Internal_rate_of_return#Numerical_solution">Wikipedia on IRR</a>
* @see <a href="http://office.microsoft.com/en-us/excel-help/irr-HP005209146.aspx">Excel IRR</a> * @see <a href="http://office.microsoft.com/en-us/excel-help/irr-HP005209146.aspx">Excel IRR</a>
*/ */
@ -89,8 +86,8 @@ public final class Irr implements Function {
* http://en.wikipedia.org/wiki/Newton%27s_method</a> * http://en.wikipedia.org/wiki/Newton%27s_method</a>
*/ */
public static double irr(double[] values, double guess) { public static double irr(double[] values, double guess) {
int maxIterationCount = 20; final int maxIterationCount = 20;
double absoluteAccuracy = 1E-7; final double absoluteAccuracy = 1E-7;
double x0 = guess; double x0 = guess;
double x1; double x1;
@ -99,11 +96,15 @@ public final class Irr implements Function {
while (i < maxIterationCount) { while (i < maxIterationCount) {
// the value of the function (NPV) and its derivate can be calculated in the same loop // the value of the function (NPV) and its derivate can be calculated in the same loop
double fValue = 0; final double factor = 1.0 + x0;
int k = 0;
double fValue = values[k];
double fDerivative = 0; double fDerivative = 0;
for (int k = 0; k < values.length; k++) { for (double denominator = factor; ++k < values.length; ) {
fValue += values[k] / Math.pow(1.0 + x0, k); final double value = values[k];
fDerivative += -k * values[k] / Math.pow(1.0 + x0, k + 1); fValue += value / denominator;
denominator *= factor;
fDerivative -= k * value / denominator;
} }
// the essense of the Newton-Raphson Method // the essense of the Newton-Raphson Method