commit
message
[NORMSINV] formula added and tested
author
Ben Vogt <[email protected]>
date
2017-07-03 19:12:43
stats
8 file(s) changed,
117 insertions(+),
7 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 52495ae..4135a3f 100644
3--- a/DOCS.md
4+++ b/DOCS.md
5@@ -1740,6 +1740,15 @@
6 @returns {number}
7 @constructor
8 ```
9+
10+### NORMSINV
11+
12+```
13+ Returns the inverse of the standard normal distribution for the given number.
14+@param probability - The probability value.
15+@returns {number}
16+@constructor
17+```
18 ## Text
19
20
21diff --git a/TODO.md b/TODO.md
22index 7ad7ef2..48dd3d5 100644
23--- a/TODO.md
24+++ b/TODO.md
25@@ -72,7 +72,6 @@ For example 64 tbs to a qt.
26 * NORMDIST
27 * NORMINV
28 * NORMSDIST
29-* NORMSINV
30 * PERMUT
31 * PROB
32 * RANK
33diff --git a/dist/Formulas/AllFormulas.js b/dist/Formulas/AllFormulas.js
34index 65d4a45..35f07c0 100644
35--- a/dist/Formulas/AllFormulas.js
36+++ b/dist/Formulas/AllFormulas.js
37@@ -158,6 +158,7 @@ exports.FORECAST = Statistical_1.FORECAST;
38 exports.POISSON = Statistical_1.POISSON;
39 exports.PERCENTRANK = Statistical_1.PERCENTRANK;
40 exports.PERCENTRANK$EXC = Statistical_1.PERCENTRANK$EXC;
41+exports.NORMSINV = Statistical_1.NORMSINV;
42 var Text_1 = require("./Text");
43 exports.ARABIC = Text_1.ARABIC;
44 exports.CHAR = Text_1.CHAR;
45diff --git a/dist/Formulas/Statistical.js b/dist/Formulas/Statistical.js
46index afd6bd5..761e5fc 100644
47--- a/dist/Formulas/Statistical.js
48+++ b/dist/Formulas/Statistical.js
49@@ -1062,3 +1062,42 @@ var PERCENTRANK$EXC = function (data, x, significance) {
50 return v;
51 };
52 exports.PERCENTRANK$EXC = PERCENTRANK$EXC;
53+/**
54+ * Returns the inverse of the standard normal distribution for the given number.
55+ * @param probability - The probability value.
56+ * @returns {number}
57+ * @constructor
58+ */
59+var NORMSINV = function (probability) {
60+ ArgsChecker_1.ArgsChecker.checkLength(arguments, 1, "NORMSINV");
61+ probability = TypeConverter_1.TypeConverter.firstValueAsNumber(probability);
62+ function erfc(x) {
63+ return 1 - MathHelpers_1.erf(x);
64+ }
65+ function erfcinv(p) {
66+ var j = 0;
67+ var x, err, t, pp;
68+ if (p >= 2)
69+ return -100;
70+ if (p <= 0)
71+ return 100;
72+ pp = (p < 1) ? p : 2 - p;
73+ t = Math.sqrt(-2 * Math.log(pp / 2));
74+ x = -0.70711 * ((2.30753 + t * 0.27061) /
75+ (1 + t * (0.99229 + t * 0.04481)) - t);
76+ for (; j < 2; j++) {
77+ err = erfc(x) - pp;
78+ x += err / (1.12837916709551257 * Math.exp(-x * x) - x * err);
79+ }
80+ return (p < 1) ? x : -x;
81+ }
82+ function inv(p, mean, std) {
83+ return -1.41421356237309505 * std * erfcinv(2 * p) + mean;
84+ }
85+ if (probability <= 0 || probability >= 1) {
86+ throw new Errors_1.NumError("Function NORMSINV parameter 1 value is " + probability +
87+ ". Valid values are between 0 and 1 exclusive.");
88+ }
89+ return inv(probability, 0, 1);
90+};
91+exports.NORMSINV = NORMSINV;
92diff --git a/src/Formulas/AllFormulas.ts b/src/Formulas/AllFormulas.ts
93index 64e38a9..5268505 100644
94--- a/src/Formulas/AllFormulas.ts
95+++ b/src/Formulas/AllFormulas.ts
96@@ -163,7 +163,8 @@ import {
97 FORECAST,
98 POISSON,
99 PERCENTRANK,
100- PERCENTRANK$EXC
101+ PERCENTRANK$EXC,
102+ NORMSINV
103 } from "./Statistical";
104 import {
105 ARABIC,
106@@ -398,5 +399,6 @@ export {
107 LINEST,
108 POISSON,
109 PERCENTRANK,
110- PERCENTRANK$EXC
111+ PERCENTRANK$EXC,
112+ NORMSINV
113 }
114\ No newline at end of file
115diff --git a/src/Formulas/Statistical.ts b/src/Formulas/Statistical.ts
116index 5bc4d98..fdc811c 100644
117--- a/src/Formulas/Statistical.ts
118+++ b/src/Formulas/Statistical.ts
119@@ -27,7 +27,8 @@ import {
120 cleanFloat,
121 mean,
122 gammafn,
123- sum
124+ sum,
125+ erf
126 } from "../Utilities/MathHelpers";
127
128
129@@ -1054,6 +1055,46 @@ var PERCENTRANK$EXC = function (data, x, significance?) {
130 };
131
132
133+/**
134+ * Returns the inverse of the standard normal distribution for the given number.
135+ * @param probability - The probability value.
136+ * @returns {number}
137+ * @constructor
138+ */
139+var NORMSINV = function (probability) {
140+ ArgsChecker.checkLength(arguments, 1, "NORMSINV");
141+ probability = TypeConverter.firstValueAsNumber(probability);
142+ function erfc(x) {
143+ return 1 - erf(x);
144+ }
145+ function erfcinv(p) {
146+ var j = 0;
147+ var x, err, t, pp;
148+ if (p >= 2)
149+ return -100;
150+ if (p <= 0)
151+ return 100;
152+ pp = (p < 1) ? p : 2 - p;
153+ t = Math.sqrt(-2 * Math.log(pp / 2));
154+ x = -0.70711 * ((2.30753 + t * 0.27061) /
155+ (1 + t * (0.99229 + t * 0.04481)) - t);
156+ for (; j < 2; j++) {
157+ err = erfc(x) - pp;
158+ x += err / (1.12837916709551257 * Math.exp(-x * x) - x * err);
159+ }
160+ return (p < 1) ? x : -x;
161+ }
162+ function inv(p, mean, std) {
163+ return -1.41421356237309505 * std * erfcinv(2 * p) + mean;
164+ }
165+ if (probability <= 0 || probability >= 1) {
166+ throw new NumError("Function NORMSINV parameter 1 value is " + probability +
167+ ". Valid values are between 0 and 1 exclusive.");
168+ }
169+ return inv(probability, 0, 1);
170+};
171+
172+
173 export {
174 AVERAGE,
175 AVERAGEA,
176@@ -1090,5 +1131,6 @@ export {
177 FORECAST,
178 POISSON,
179 PERCENTRANK,
180- PERCENTRANK$EXC
181+ PERCENTRANK$EXC,
182+ NORMSINV
183 }
184\ No newline at end of file
185diff --git a/tests/Formulas/StatisticalTest.ts b/tests/Formulas/StatisticalTest.ts
186index 539e959..f9bf91e 100644
187--- a/tests/Formulas/StatisticalTest.ts
188+++ b/tests/Formulas/StatisticalTest.ts
189@@ -34,7 +34,8 @@ import {
190 FORECAST,
191 POISSON,
192 PERCENTRANK,
193- PERCENTRANK$EXC
194+ PERCENTRANK$EXC,
195+ NORMSINV
196 } from "../../src/Formulas/Statistical";
197 import * as ERRORS from "../../src/Errors";
198 import {
199@@ -748,4 +749,16 @@ test("PERCENTRANK$EXC", function() {
200 catchAndAssertEquals(function() {
201 PERCENTRANK$EXC([1, 5, 3, 7, 3, 2, 6, 8, 4, 9, 0, 3, 1], -1);
202 }, ERRORS.NA_ERROR);
203+});
204+
205+
206+test("NORMSINV", function() {
207+ assertEquals(NORMSINV(0.1), -1.2815515655446006);
208+ assertEquals(NORMSINV(0.4), -0.2533471031357999);
209+ catchAndAssertEquals(function() {
210+ NORMSINV(0);
211+ }, ERRORS.NUM_ERROR);
212+ catchAndAssertEquals(function() {
213+ NORMSINV(1);
214+ }, ERRORS.NUM_ERROR);
215 });
216\ No newline at end of file
217diff --git a/tests/SheetFormulaTest.ts b/tests/SheetFormulaTest.ts
218index 8b17052..910dd0c 100644
219--- a/tests/SheetFormulaTest.ts
220+++ b/tests/SheetFormulaTest.ts
221@@ -781,6 +781,10 @@ test("Sheet PERCENTRANK.EXC", function(){
222 assertFormulaEquals('=PERCENTRANK.EXC([1], 1)', 1);
223 });
224
225+test("Sheet NORMSINV", function(){
226+ assertFormulaEquals('=NORMSINV(0.1)', -1.2815515655446006);
227+});
228+
229 test("Sheet *", function(){
230 assertFormulaEquals('= 10 * 10', 100);
231 assertFormulaEquals('= 10 * 0', 0);