commit
message
[ALL] checking for DIV_ZERO errors
author
Ben Vogt <[email protected]>
date
2017-04-02 19:32:38
stats
5 file(s) changed,
41 insertions(+),
21 deletions(-)
files
README.md
src/RawFormulas/Financial.ts
src/RawFormulas/RawFormulas.ts
src/RawFormulas/Statistical.ts
src/RawFormulas/Utils.ts
1diff --git a/README.md b/README.md
2index f3512bf..8d52f4a 100644
3--- a/README.md
4+++ b/README.md
5@@ -34,10 +34,6 @@ Group by error type and have some useful functions that will call with 0, N, N+1
6 checker. Also, test for *all possible* errors that could be thrown, and *all possible types* that could be passed in.
7 Another thing to think about would be throwing custom errors if an object is passed in.
8
9-### DIV_ZERO Error
10-This error is thrown every time we're about to divide by zero in a formula. There are definitely a couple formulas that
11-don't check for this, and they should.
12-
13 ### jStat functions should know their caller
14 Either through `arguments`, or directly passed in like `mean("FORMULA", [10, 20, 30])`
15
16diff --git a/src/RawFormulas/Financial.ts b/src/RawFormulas/Financial.ts
17index e9131f8..7dae7f2 100644
18--- a/src/RawFormulas/Financial.ts
19+++ b/src/RawFormulas/Financial.ts
20@@ -1,6 +1,7 @@
21 import {
22 ArgsChecker,
23- TypeCaster
24+ TypeCaster,
25+ checkForDevideByZero
26 } from "./Utils";
27 import {
28 CellError
29@@ -52,7 +53,7 @@ var DDB = function (...values) : number {
30 var total = 0;
31 var current = 0;
32 for (var i = 1; i <= period; i++) {
33- current = Math.min((cost - total) * (factor / life), (cost - salvage - total));
34+ current = Math.min((cost - total) * (factor / checkForDevideByZero(life)), (cost - salvage - total));
35 total += current;
36 }
37 return current;
38@@ -103,6 +104,9 @@ var DB = function (...values) : number {
39 if (salvage >= cost) {
40 return 0;
41 }
42+ if (cost === 0 && salvage !== 0) {
43+ throw new CellError(ERRORS.DIV_ZERO_ERROR, "Evaluation of function DB cause a divide by zero error.")
44+ }
45 var rate = (1 - Math.pow(salvage / cost, 1 / life));
46 var initial = cost * rate * month / 12;
47 var total = initial;
48@@ -142,7 +146,12 @@ var DOLLAR = function (...values) : number {
49 var v = TypeCaster.firstValueAsNumber(values[0]);
50 var places = values.length === 2 ? TypeCaster.firstValueAsNumber(values[1]) : 2;
51 var sign = (v > 0) ? 1 : -1;
52- return sign * (Math.floor(Math.abs(v) * Math.pow(10, places))) / Math.pow(10, places);
53+ var divisor = sign * (Math.floor(Math.abs(v) * Math.pow(10, places)));
54+ var pow = Math.pow(10, places);
55+ if (pow === 0 && divisor !== 0) {
56+ throw new CellError(ERRORS.DIV_ZERO_ERROR, "Evaluation of function DOLLAR cause a divide by zero error.")
57+ }
58+ return divisor / pow;
59 };
60
61
62diff --git a/src/RawFormulas/RawFormulas.ts b/src/RawFormulas/RawFormulas.ts
63index 0aaa2a1..962f2cf 100644
64--- a/src/RawFormulas/RawFormulas.ts
65+++ b/src/RawFormulas/RawFormulas.ts
66@@ -119,18 +119,6 @@ import {
67 YEARFRAC
68 } from "./Date"
69
70-import {
71- CriteriaFunctionFactory,
72- ArgsChecker,
73- Filter,
74- TypeCaster,
75- Serializer
76-} from "./Utils";
77-import {
78- CellError
79-} from "../Errors"
80-import * as ERRORS from "../Errors"
81-
82 var ACCRINT = Formula["ACCRINT"];
83 var CONVERT = Formula["CONVERT"];
84
85diff --git a/src/RawFormulas/Statistical.ts b/src/RawFormulas/Statistical.ts
86index adb7f9e..742244f 100644
87--- a/src/RawFormulas/Statistical.ts
88+++ b/src/RawFormulas/Statistical.ts
89@@ -144,6 +144,9 @@ var AVEDEV = function (...values) {
90 result = result + TypeCaster.valueToNumber(flatValues[i]);
91 count++;
92 }
93+ if (count === 0) {
94+ throw new CellError(ERRORS.DIV_ZERO_ERROR, "Evaluation of function AVEDEV caused a devide by zero error.");
95+ }
96 var mean = result / count;
97
98 for (var i = 0; i < flatValues.length; i++) {
99@@ -175,6 +178,9 @@ var AVERAGEA = function (...values) {
100 count++;
101 }
102 }
103+ if (count === 0) {
104+ throw new CellError(ERRORS.DIV_ZERO_ERROR, "Evaluation of function AVEDEV caused a devide by zero error.");
105+ }
106 return result / count;
107 };
108
109@@ -205,6 +211,9 @@ var CORREL = function (...values) : number {
110 return sum;
111 }
112 function mean(arr) {
113+ if (arr.length === 0) {
114+ throw new CellError(ERRORS.DIV_ZERO_ERROR, "Evaluation of function CORREL caused a divide by zero error.");
115+ }
116 return sum(arr) / arr.length;
117 }
118 function sumsqerr(arr) {
119@@ -248,7 +257,7 @@ var CORREL = function (...values) : number {
120 if (stdevArr1 === 0 || stdevArr2 === 0) {
121 throw new CellError(ERRORS.DIV_ZERO_ERROR, "Evaluation of function CORREL caused a divide by zero error.");
122 }
123- return covariance(arr1, arr2) / stdev(arr1, 1) / stdev(arr2, 1);
124+ return covariance(arr1, arr2) / stdevArr1 / stdevArr2;
125 };
126
127 /**
128diff --git a/src/RawFormulas/Utils.ts b/src/RawFormulas/Utils.ts
129index 4e4dd5a..18f8037 100644
130--- a/src/RawFormulas/Utils.ts
131+++ b/src/RawFormulas/Utils.ts
132@@ -897,6 +897,22 @@ class Serializer {
133 }
134 }
135
136+/**
137+ * Catches divide by zero situations and throws them as errors
138+ * @param n number to check
139+ * @returns {number} n as long as it's not zero.
140+ */
141+var checkForDevideByZero = function(n : number) : number {
142+ n = +n; // Coerce to number.
143+ if (!n) { // Matches +0, -0, NaN
144+ throw new CellError(ERRORS.DIV_ZERO_ERROR, "Evaluation of function caused a divide by zero error.");
145+ }
146+ return n;
147+};
148+
149+var divideAndCheck
150+
151+
152
153 export {
154 ArgsChecker,
155@@ -904,5 +920,6 @@ export {
156 DateRegExBuilder,
157 Filter,
158 Serializer,
159- TypeCaster
160+ TypeCaster,
161+ checkForDevideByZero
162 }
163\ No newline at end of file