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);