Skip to content

Commit

Permalink
[github-733] Fix rate order in Mirr function. Thanks to Aleksandrs Ja…
Browse files Browse the repository at this point in the history
…nsons. This closes #733

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1922095 13f79535-47bb-0310-9956-ffa450edef68
  • Loading branch information
pjfanning committed Nov 25, 2024
1 parent 0d63f9a commit edb9aea
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 35 deletions.
25 changes: 9 additions & 16 deletions poi/src/main/java/org/apache/poi/ss/formula/functions/Mirr.java
Original file line number Diff line number Diff line change
Expand Up @@ -56,23 +56,20 @@ protected int getMaxNumOperands() {
@Override
protected double evaluate(double[] values) throws EvaluationException {

double financeRate = values[values.length-1];
double reinvestRate = values[values.length-2];
double financeRate = values[values.length-2];
double reinvestRate = values[values.length-1];

double[] mirrValues = Arrays.copyOf(values, values.length - 2);

boolean mirrValuesAreAllNegatives = true;
for (double mirrValue : mirrValues) {
mirrValuesAreAllNegatives &= mirrValue < 0;
}
if (mirrValuesAreAllNegatives) {
return -1.0d;
}

boolean mirrValuesAreAllPositives = true;
for (double mirrValue : mirrValues) {
mirrValuesAreAllNegatives &= mirrValue < 0;
mirrValuesAreAllPositives &= mirrValue > 0;
}
if (mirrValuesAreAllNegatives) {
return -1.0d;
}
if (mirrValuesAreAllPositives) {
throw new EvaluationException(ErrorEval.DIV_ZERO);
}
Expand All @@ -87,15 +84,11 @@ private static double mirr(double[] in, double financeRate, double reinvestRate)
double fv = 0;

int indexN = 0;
for (double anIn : in) {
if (anIn < 0) {
pv += anIn / Math.pow(1 + financeRate + reinvestRate, indexN++);
}
}

for (double anIn : in) {
if (anIn > 0) {
fv += anIn * Math.pow(1 + financeRate, numOfYears - indexN++);
fv += anIn * Math.pow(1 + reinvestRate, numOfYears - indexN++);
} else if (anIn < 0) {
pv += anIn / Math.pow(1 + financeRate, indexN++);
}
}

Expand Down
39 changes: 20 additions & 19 deletions poi/src/test/java/org/apache/poi/ss/formula/functions/TestMirr.java
Original file line number Diff line number Diff line change
Expand Up @@ -44,43 +44,44 @@ void testMirr() throws EvaluationException {
Mirr mirr = new Mirr();
double mirrValue;

double financeRate = 0.12;
double reinvestRate = 0.1;
double[] values = {-120000d, 39000d, 30000d, 21000d, 37000d, 46000d, reinvestRate, financeRate};
// MIRR should not failed with these parameters
double financeRate = 0.1;
double reinvestRate = 0.12;
double[] values = {-120000d, 39000d, 30000d, 21000d, 37000d, 46000d, financeRate, reinvestRate};
mirrValue = mirr.evaluate(values);
assertEquals(0.126094130366, mirrValue, 0.0000000001);

reinvestRate = 0.05;
financeRate = 0.08;
values = new double[]{-7500d, 3000d, 5000d, 1200d, 4000d, reinvestRate, financeRate};
// MIRR should not failed with these parameters
financeRate = 0.05;
reinvestRate = 0.08;
values = new double[]{-7500d, 3000d, 5000d, 1200d, 4000d, financeRate, reinvestRate};
mirrValue = mirr.evaluate(values);
assertEquals(0.18736225093, mirrValue, 0.0000000001);

reinvestRate = 0.065;
financeRate = 0.1;
values = new double[]{-10000, 3400d, 6500d, 1000d, reinvestRate, financeRate};
// MIRR should not failed with these parameters
financeRate = 0.065;
reinvestRate = 0.1;
values = new double[]{-10000, 3400d, 6500d, 1000d, financeRate, reinvestRate};
mirrValue = mirr.evaluate(values);
assertEquals(0.07039493966, mirrValue, 0.0000000001);

reinvestRate = 0.07;
financeRate = 0.01;
values = new double[]{-10000d, -3400d, -6500d, -1000d, reinvestRate, financeRate};
// MIRR should not failed with these parameters
financeRate = 0.07;
reinvestRate = 0.01;
values = new double[]{-10000d, -3400d, -6500d, -1000d, financeRate, reinvestRate};
mirrValue = mirr.evaluate(values);
assertEquals(-1, mirrValue, 0.0);

financeRate = 0.1;
reinvestRate = 0.12;
values = new double[]{-1000d, -4000d, 5000d, 2000d, financeRate, reinvestRate};
mirrValue = mirr.evaluate(values);
assertEquals(0.179085686035, mirrValue, 0.0000000001);
}

@Test
void testMirrErrors_expectDIV0() {
Mirr mirr = new Mirr();

double reinvestRate = 0.05;
double financeRate = 0.08;
double[] incomes = {120000d, 39000d, 30000d, 21000d, 37000d, 46000d, reinvestRate, financeRate};
double reinvestRate = 0.05;
double[] incomes = {120000d, 39000d, 30000d, 21000d, 37000d, 46000d, financeRate, reinvestRate};

EvaluationException e = assertThrows(EvaluationException.class, () -> mirr.evaluate(incomes));
assertEquals(ErrorEval.DIV_ZERO, e.getErrorEval());
Expand Down Expand Up @@ -117,7 +118,7 @@ void testMirrFromSpreadsheet() {
HSSFSheet sheet = wb.getSheet("Mirr");
HSSFFormulaEvaluator fe = new HSSFFormulaEvaluator(wb);
int failureCount = 0;
int[] resultRows = {9, 19, 29, 45};
int[] resultRows = {9, 19, 29, 45, 53};

for (int rowNum : resultRows) {
HSSFRow row = sheet.getRow(rowNum);
Expand Down
Binary file modified test-data/spreadsheet/mirrTest.xls
Binary file not shown.

0 comments on commit edb9aea

Please sign in to comment.