spreadsheet
typeScript/javascript spreadsheet parser, with formulas.
git clone https://git.vogt.world/spreadsheet.git
Log | Files | README.md
← Commit log
commit
message
[NPER] formula added and tested
author
Ben Vogt <[email protected]>
date
2017-06-29 00:36:52
stats
8 file(s) changed, 112 insertions(+), 6 deletions(-)
files
DOCS.md
TODO.md
dist/Formulas/AllFormulas.js
dist/Formulas/Financial.js
src/Formulas/AllFormulas.ts
src/Formulas/Financial.ts
tests/Formulas/FinancialTest.ts
tests/SheetFormulaTest.ts
  1diff --git a/DOCS.md b/DOCS.md
  2index 3f5aa20..8783f4d 100644
  3--- a/DOCS.md
  4+++ b/DOCS.md
  5@@ -469,6 +469,19 @@
  6 @returns {number} 
  7 @constructor TODO: This function can return results that are prone to floating point precision errors.
  8 ```
  9+
 10+### NPER 
 11+
 12+```
 13+  Returns the number of payment for an investment. Number is based on constant-amount payments made periodically and a constant interest rate. 
 14+@param rate - The interest rate. 
 15+@param payment - The amount of each payment. 
 16+@param present - THe current value. 
 17+@param future - [OPTIONAL] - The future value remaining after the final payment has been made. 
 18+@param type [OPTIONAL 0 by default] - 1 indicates payments are due at the beginning of each period. 0 indicates payments are due at the end of each period. 
 19+@returns {number} 
 20+@constructor
 21+```
 22 ## Info
 23 
 24 
 25diff --git a/TODO.md b/TODO.md
 26index c8e65a1..bdd2605 100644
 27--- a/TODO.md
 28+++ b/TODO.md
 29@@ -144,7 +144,6 @@ For example 64 tbs to a qt.
 30 * IRR
 31 * MIRR
 32 * NOMINAL
 33-* NPER
 34 * PPMT - Similar to PMT, which is already written.
 35 * PRICE
 36 * PRICEDISC
 37diff --git a/dist/Formulas/AllFormulas.js b/dist/Formulas/AllFormulas.js
 38index f4836ab..dac8243 100644
 39--- a/dist/Formulas/AllFormulas.js
 40+++ b/dist/Formulas/AllFormulas.js
 41@@ -113,6 +113,7 @@ exports.EFFECT = Financial_1.EFFECT;
 42 exports.SYD = Financial_1.SYD;
 43 exports.SLN = Financial_1.SLN;
 44 exports.NPV = Financial_1.NPV;
 45+exports.NPER = Financial_1.NPER;
 46 var Statistical_1 = require("./Statistical");
 47 exports.AVERAGE = Statistical_1.AVERAGE;
 48 exports.AVERAGEA = Statistical_1.AVERAGEA;
 49diff --git a/dist/Formulas/Financial.js b/dist/Formulas/Financial.js
 50index 34699bb..8ed7be2 100644
 51--- a/dist/Formulas/Financial.js
 52+++ b/dist/Formulas/Financial.js
 53@@ -494,3 +494,35 @@ var NPV = function (rate) {
 54     return value;
 55 };
 56 exports.NPV = NPV;
 57+/**
 58+ * Returns the number of payment for an investment. Number is based on constant-amount payments made periodically and a
 59+ * constant interest rate.
 60+ * @param rate - The interest rate.
 61+ * @param payment - The amount of each payment.
 62+ * @param present - THe current value.
 63+ * @param future - [OPTIONAL] - The future value remaining after the final payment has been made.
 64+ * @param type [OPTIONAL 0 by default] - 1 indicates payments are due at the beginning of each period. 0 indicates
 65+ * payments are due at the end of each period.
 66+ * @returns {number}
 67+ * @constructor
 68+ */
 69+var NPER = function (rate, payment, present, future, type) {
 70+    ArgsChecker_1.ArgsChecker.checkLengthWithin(arguments, 3, 5, "NPER");
 71+    rate = TypeConverter_1.TypeConverter.firstValueAsNumber(rate);
 72+    payment = TypeConverter_1.TypeConverter.firstValueAsNumber(payment);
 73+    present = TypeConverter_1.TypeConverter.firstValueAsNumber(present);
 74+    type = (typeof type === 'undefined') ? 0 : TypeConverter_1.TypeConverter.firstValueAsNumber(type);
 75+    future = (typeof future === 'undefined') ? 0 : TypeConverter_1.TypeConverter.firstValueAsNumber(future);
 76+    var num = payment * (1 + rate * type) - future * rate;
 77+    var den = (present * rate + payment * (1 + rate * type));
 78+    if (den === 0) {
 79+        throw new Errors_1.DivZeroError("Evaluation of function NPER cause a divide by zero error.");
 80+    }
 81+    var div = Math.log(1 + rate);
 82+    var logNumDen = Math.log(num / den);
 83+    if (isNaN(logNumDen)) {
 84+        throw new Errors_1.NumError("Parameters given function NPER are not possible.");
 85+    }
 86+    return logNumDen / div;
 87+};
 88+exports.NPER = NPER;
 89diff --git a/src/Formulas/AllFormulas.ts b/src/Formulas/AllFormulas.ts
 90index 35b048d..e8fac3f 100644
 91--- a/src/Formulas/AllFormulas.ts
 92+++ b/src/Formulas/AllFormulas.ts
 93@@ -116,7 +116,8 @@ import {
 94   EFFECT,
 95   SYD,
 96   SLN,
 97-  NPV
 98+  NPV,
 99+  NPER
100 } from "./Financial";
101 import {
102   AVERAGE,
103@@ -371,5 +372,6 @@ export {
104   FORECAST,
105   SYD,
106   SLN,
107-  NPV
108+  NPV,
109+  NPER
110 }
111\ No newline at end of file
112diff --git a/src/Formulas/Financial.ts b/src/Formulas/Financial.ts
113index 448f1c4..7f00899 100644
114--- a/src/Formulas/Financial.ts
115+++ b/src/Formulas/Financial.ts
116@@ -503,6 +503,38 @@ var NPV = function (rate, ...values) {
117   return value;
118 };
119 
120+/**
121+ * Returns the number of payment for an investment. Number is based on constant-amount payments made periodically and a
122+ * constant interest rate.
123+ * @param rate - The interest rate.
124+ * @param payment - The amount of each payment.
125+ * @param present - THe current value.
126+ * @param future - [OPTIONAL] - The future value remaining after the final payment has been made.
127+ * @param type [OPTIONAL 0 by default] - 1 indicates payments are due at the beginning of each period. 0 indicates
128+ * payments are due at the end of each period.
129+ * @returns {number}
130+ * @constructor
131+ */
132+var NPER = function (rate, payment, present, future?, type?) {
133+  ArgsChecker.checkLengthWithin(arguments, 3, 5, "NPER");
134+  rate = TypeConverter.firstValueAsNumber(rate);
135+  payment = TypeConverter.firstValueAsNumber(payment);
136+  present = TypeConverter.firstValueAsNumber(present);
137+  type = (typeof type === 'undefined') ? 0 : TypeConverter.firstValueAsNumber(type);
138+  future = (typeof future === 'undefined') ? 0 : TypeConverter.firstValueAsNumber(future);
139+  var num = payment * (1 + rate * type) - future * rate;
140+  var den = (present * rate + payment * (1 + rate * type));
141+  if (den === 0) {
142+    throw new DivZeroError("Evaluation of function NPER cause a divide by zero error.");
143+  }
144+  var div = Math.log(1 + rate);
145+  var logNumDen = Math.log(num / den);
146+  if (isNaN(logNumDen)) {
147+    throw new NumError("Parameters given function NPER are not possible.");
148+  }
149+  return  logNumDen / div;
150+};
151+
152 
153 export {
154   ACCRINT,
155@@ -517,5 +549,6 @@ export {
156   PMT,
157   SYD,
158   SLN,
159-  NPV
160+  NPV,
161+  NPER
162 }
163\ No newline at end of file
164diff --git a/tests/Formulas/FinancialTest.ts b/tests/Formulas/FinancialTest.ts
165index 222f1a9..0ea0987 100644
166--- a/tests/Formulas/FinancialTest.ts
167+++ b/tests/Formulas/FinancialTest.ts
168@@ -11,7 +11,8 @@ import {
169   PMT,
170   SYD,
171   SLN,
172-  NPV
173+  NPV,
174+  NPER
175 } from "../../src/Formulas/Financial";
176 import {
177   DATE
178@@ -321,3 +322,24 @@ test("NPV", function() {
179     NPV.apply(this, [10, 10, 20, "str"]);
180   }, ERRORS.VALUE_ERROR);
181 });
182+
183+
184+test("NPER", function() {
185+  assertEquals(NPER(0.04, 100, 4000, 0, 0), -24.362418941571317);
186+  assertEquals(NPER(0.04, 100, 4000), -24.362418941571317);
187+  assertEquals(NPER(0.02, 100, 4000, 0, 0), -29.68225660720854);
188+  assertEquals(NPER(0.01, 100, 4000, 0, 0), -33.815180780052486);
189+  assertEquals(NPER(0.04, -50, 1000, 20, 0), 41.44012515117696);
190+  assertEquals(NPER(-0.04, -50, 1000, 20, 0), 14.79388878297825);
191+  assertEquals(NPER(0.04, -50, 1000, 2000, 1), 61.13849239372526);
192+  assertEquals(NPER(0.04, -50, 1000, 2000, 0), 65.39782556827234);
193+  catchAndAssertEquals(function() {
194+    NPER(0.04, 50, 1000, 2000, 0);
195+  }, ERRORS.NUM_ERROR);
196+  catchAndAssertEquals(function() {
197+    NPER.apply(this, [0.04, 100]);
198+  }, ERRORS.NA_ERROR);
199+  catchAndAssertEquals(function() {
200+    NPER.apply(this, [0.04, -50, 1000, 2000, 0, 22]);
201+  }, ERRORS.NA_ERROR);
202+});
203diff --git a/tests/SheetFormulaTest.ts b/tests/SheetFormulaTest.ts
204index 3fb0a7c..3810e5a 100644
205--- a/tests/SheetFormulaTest.ts
206+++ b/tests/SheetFormulaTest.ts
207@@ -731,6 +731,9 @@ test("Sheet SLN", function(){
208   assertFormulaEquals('=SLN(100, 22, 10)', 7.80);
209 });
210 
211+test("Sheet NPER", function(){
212+  assertFormulaEquals('=NPER(0.04, 100, 4000, 0, 0)', -24.362418941571317);
213+});
214 
215 test("Sheet *", function(){
216   assertFormulaEquals('= 10 * 10', 100);