spreadsheet
typeScript/javascript spreadsheet parser, with formulas.
git clone https://git.vogt.world/spreadsheet.git
Log | Files | README.md
← Commit log
commit
message
[NEGBINOMDIST] formula added and tested
author
Ben Vogt <[email protected]>
date
2017-07-03 23:19:36
stats
8 file(s) changed, 170 insertions(+), 6 deletions(-)
files
DOCS.md
TODO.md
dist/Formulas/AllFormulas.js
dist/Formulas/Statistical.js
src/Formulas/AllFormulas.ts
src/Formulas/Statistical.ts
tests/Formulas/StatisticalTest.ts
tests/SheetFormulaTest.ts
  1diff --git a/DOCS.md b/DOCS.md
  2index 7c2e38e..1164e9c 100644
  3--- a/DOCS.md
  4+++ b/DOCS.md
  5@@ -1781,6 +1781,17 @@
  6 @returns {number} 
  7 @constructor
  8 ```
  9+
 10+### BINOMDIST 
 11+
 12+```
 13+  Returns the negative binomial distribution. 
 14+@param k - The value returned for unsuccessful tests. 
 15+@param r - The value returned for successful tests. 
 16+@param p - The probability of the success of an attempt, between 0 and 1 inclusively. 
 17+@returns {number} 
 18+@constructor
 19+```
 20 ## Text
 21 
 22 
 23diff --git a/TODO.md b/TODO.md
 24index 5db3218..765bd85 100644
 25--- a/TODO.md
 26+++ b/TODO.md
 27@@ -68,7 +68,6 @@ For example 64 tbs to a qt.
 28 * LOGINV
 29 * LOGNORMDIST
 30 * MODE
 31-* NEGBINOMDIST
 32 * PERMUT
 33 * PROB
 34 * RANK
 35diff --git a/dist/Formulas/AllFormulas.js b/dist/Formulas/AllFormulas.js
 36index 6db97e2..6804a90 100644
 37--- a/dist/Formulas/AllFormulas.js
 38+++ b/dist/Formulas/AllFormulas.js
 39@@ -162,6 +162,7 @@ exports.NORMSINV = Statistical_1.NORMSINV;
 40 exports.NORMSDIST = Statistical_1.NORMSDIST;
 41 exports.NORMDIST = Statistical_1.NORMDIST;
 42 exports.NORMINV = Statistical_1.NORMINV;
 43+exports.NEGBINOMDIST = Statistical_1.NEGBINOMDIST;
 44 var Text_1 = require("./Text");
 45 exports.ARABIC = Text_1.ARABIC;
 46 exports.CHAR = Text_1.CHAR;
 47diff --git a/dist/Formulas/Statistical.js b/dist/Formulas/Statistical.js
 48index 051fa33..788813f 100644
 49--- a/dist/Formulas/Statistical.js
 50+++ b/dist/Formulas/Statistical.js
 51@@ -1217,3 +1217,64 @@ var NORMINV = function (probability, meanVal, standDev) {
 52     return inv(probability, meanVal, standDev);
 53 };
 54 exports.NORMINV = NORMINV;
 55+/**
 56+ * Returns the negative binomial distribution.
 57+ * @param k - The value returned for unsuccessful tests.
 58+ * @param r - The value returned for successful tests.
 59+ * @param p - The probability of the success of an attempt, between 0 and 1 inclusively.
 60+ * @returns {number}
 61+ * @constructor
 62+ */
 63+var NEGBINOMDIST = function (k, r, p) {
 64+    ArgsChecker_1.ArgsChecker.checkLength(arguments, 3, "NEGBINOMDIST");
 65+    function _gammaln(x) {
 66+        var j = 0;
 67+        var cof = [
 68+            76.18009172947146, -86.50532032941677, 24.01409824083091,
 69+            -1.231739572450155, 0.1208650973866179e-2, -0.5395239384953e-5
 70+        ];
 71+        var ser = 1.000000000190015;
 72+        var xx, y, tmp;
 73+        tmp = (y = xx = x) + 5.5;
 74+        tmp -= (xx + 0.5) * Math.log(tmp);
 75+        for (; j < 6; j++)
 76+            ser += cof[j] / ++y;
 77+        return Math.log(2.5066282746310005 * ser / xx) - tmp;
 78+    }
 79+    function _combinationln(n, m) {
 80+        return _factorialln(n) - _factorialln(m) - _factorialln(n - m);
 81+    }
 82+    function _factorialln(n) {
 83+        return n < 0 ? NaN : _gammaln(n + 1);
 84+    }
 85+    function _factorial(n) {
 86+        return n < 0 ? NaN : MathHelpers_1.gammafn(n + 1);
 87+    }
 88+    function _combination(n, m) {
 89+        return (n > 170 || m > 170)
 90+            ? Math.exp(_combinationln(n, m))
 91+            : (_factorial(n) / _factorial(m)) / _factorial(n - m);
 92+    }
 93+    function _pdf(k, r, p) {
 94+        return k !== (k | 0)
 95+            ? 0
 96+            : k < 0
 97+                ? 0
 98+                : _combination(k + r - 1, r - 1) * Math.pow(1 - p, k) * Math.pow(p, r);
 99+    }
100+    k = TypeConverter_1.TypeConverter.firstValueAsNumber(k);
101+    r = TypeConverter_1.TypeConverter.firstValueAsNumber(r);
102+    p = TypeConverter_1.TypeConverter.firstValueAsNumber(p);
103+    if (k < 1) {
104+        throw new Errors_1.NumError("Function NEGBINOMDIST parameter 1 value is " + k + ". Should be greater than 0.");
105+    }
106+    if (r < 1) {
107+        throw new Errors_1.NumError("Function NEGBINOMDIST parameter 2 value is " + r + ". Should be greater than 0.");
108+    }
109+    if (p < 0 || p > 1) {
110+        throw new Errors_1.NumError("Function NEGBINOMDIST parameter 3 value is " + p +
111+            ". Valid values are between 0 and 1 inclusive.");
112+    }
113+    return _pdf(k, r, p);
114+};
115+exports.NEGBINOMDIST = NEGBINOMDIST;
116diff --git a/src/Formulas/AllFormulas.ts b/src/Formulas/AllFormulas.ts
117index cf885e3..883f92a 100644
118--- a/src/Formulas/AllFormulas.ts
119+++ b/src/Formulas/AllFormulas.ts
120@@ -167,7 +167,8 @@ import {
121   NORMSINV,
122   NORMSDIST,
123   NORMDIST,
124-  NORMINV
125+  NORMINV,
126+  NEGBINOMDIST
127 } from "./Statistical";
128 import {
129   ARABIC,
130@@ -406,5 +407,6 @@ export {
131   NORMSINV,
132   NORMSDIST,
133   NORMDIST,
134-  NORMINV
135+  NORMINV,
136+  NEGBINOMDIST
137 }
138\ No newline at end of file
139diff --git a/src/Formulas/Statistical.ts b/src/Formulas/Statistical.ts
140index 5a11ab1..df359e3 100644
141--- a/src/Formulas/Statistical.ts
142+++ b/src/Formulas/Statistical.ts
143@@ -1219,6 +1219,68 @@ var NORMINV = function (probability, meanVal, standDev) {
144 };
145 
146 
147+/**
148+ * Returns the negative binomial distribution.
149+ * @param k - The value returned for unsuccessful tests.
150+ * @param r - The value returned for successful tests.
151+ * @param p - The probability of the success of an attempt, between 0 and 1 inclusively.
152+ * @returns {number}
153+ * @constructor
154+ */
155+var NEGBINOMDIST = function (k, r, p) {
156+  ArgsChecker.checkLength(arguments, 3, "NEGBINOMDIST");
157+  function _gammaln(x) {
158+    var j = 0;
159+    var cof = [
160+      76.18009172947146, -86.50532032941677, 24.01409824083091,
161+      -1.231739572450155, 0.1208650973866179e-2, -0.5395239384953e-5
162+    ];
163+    var ser = 1.000000000190015;
164+    var xx, y, tmp;
165+    tmp = (y = xx = x) + 5.5;
166+    tmp -= (xx + 0.5) * Math.log(tmp);
167+    for (; j < 6; j++)
168+      ser += cof[j] / ++y;
169+    return Math.log(2.5066282746310005 * ser / xx) - tmp;
170+  }
171+  function _combinationln(n, m) {
172+    return _factorialln(n) - _factorialln(m) - _factorialln(n - m);
173+  }
174+  function _factorialln(n) {
175+    return n < 0 ? NaN : _gammaln(n + 1);
176+  }
177+  function _factorial(n) {
178+    return n < 0 ? NaN : gammafn(n + 1);
179+  }
180+  function _combination(n, m) {
181+    return (n > 170 || m > 170)
182+      ? Math.exp(_combinationln(n, m))
183+      : (_factorial(n) / _factorial(m)) / _factorial(n - m);
184+  }
185+  function _pdf(k, r, p) {
186+    return k !== (k | 0)
187+      ? 0
188+      : k < 0
189+      ? 0
190+      : _combination(k + r - 1, r - 1) * Math.pow(1 - p, k) * Math.pow(p, r);
191+  }
192+  k = TypeConverter.firstValueAsNumber(k);
193+  r = TypeConverter.firstValueAsNumber(r);
194+  p = TypeConverter.firstValueAsNumber(p);
195+  if (k < 1) {
196+    throw new NumError("Function NEGBINOMDIST parameter 1 value is " + k + ". Should be greater than 0.");
197+  }
198+  if (r < 1) {
199+    throw new NumError("Function NEGBINOMDIST parameter 2 value is " + r + ". Should be greater than 0.");
200+  }
201+  if (p < 0 || p > 1) {
202+    throw new NumError("Function NEGBINOMDIST parameter 3 value is " + p +
203+        ". Valid values are between 0 and 1 inclusive.");
204+  }
205+  return _pdf(k, r, p);
206+};
207+
208+
209 export {
210   AVERAGE,
211   AVERAGEA,
212@@ -1259,5 +1321,6 @@ export {
213   NORMSINV,
214   NORMSDIST,
215   NORMDIST,
216-  NORMINV
217+  NORMINV,
218+  NEGBINOMDIST
219 }
220\ No newline at end of file
221diff --git a/tests/Formulas/StatisticalTest.ts b/tests/Formulas/StatisticalTest.ts
222index 032366a..a797fba 100644
223--- a/tests/Formulas/StatisticalTest.ts
224+++ b/tests/Formulas/StatisticalTest.ts
225@@ -38,7 +38,8 @@ import {
226   NORMSINV,
227   NORMSDIST,
228   NORMDIST,
229-  NORMINV
230+  NORMINV,
231+  NEGBINOMDIST
232 } from "../../src/Formulas/Statistical";
233 import * as ERRORS from "../../src/Errors";
234 import {
235@@ -820,4 +821,26 @@ test("NORMINV", function() {
236   catchAndAssertEquals(function() {
237     NORMINV.apply(this, [0.2, 0.8, 6, 1]);
238   }, ERRORS.NA_ERROR);
239+});
240+
241+
242+test("NEGBINOMDIST", function() {
243+  assertEquals(NEGBINOMDIST(5, 3, 0.2), 0.05505024000000004);
244+  assertEquals(NEGBINOMDIST(10, 3, 0.2), 0.05669356830720007);
245+  assertEquals(NEGBINOMDIST(10, 7, 0.8), 0.00017197049053183967);
246+  catchAndAssertEquals(function() {
247+    NEGBINOMDIST.apply(this, [-10, 7, 0.8]);
248+  }, ERRORS.NUM_ERROR);
249+  catchAndAssertEquals(function() {
250+    NEGBINOMDIST.apply(this, [10, -7, 0.8]);
251+  }, ERRORS.NUM_ERROR);
252+  catchAndAssertEquals(function() {
253+    NEGBINOMDIST.apply(this, [10, 7, -0.8]);
254+  }, ERRORS.NUM_ERROR);
255+  catchAndAssertEquals(function() {
256+    NEGBINOMDIST.apply(this, [0.2, 0.8]);
257+  }, ERRORS.NA_ERROR);
258+  catchAndAssertEquals(function() {
259+    NEGBINOMDIST.apply(this, [0.2, 0.8, 6, 1]);
260+  }, ERRORS.NA_ERROR);
261 });
262\ No newline at end of file
263diff --git a/tests/SheetFormulaTest.ts b/tests/SheetFormulaTest.ts
264index 02c5dc2..c28333d 100644
265--- a/tests/SheetFormulaTest.ts
266+++ b/tests/SheetFormulaTest.ts
267@@ -793,6 +793,10 @@ test("Sheet NORMINV", function(){
268   assertFormulaEquals('=NORMINV(0.8, 0, 6)', 5.049727401437487);
269 });
270 
271+test("Sheet NEGBINOMDIST", function(){
272+  assertFormulaEquals('=NEGBINOMDIST(5, 3, 0.2)', 0.05505024000000004);
273+});
274+
275 test("Sheet *", function(){
276   assertFormulaEquals('= 10 * 10', 100);
277   assertFormulaEquals('= 10 * 0', 0);