spreadsheet
typeScript/javascript spreadsheet parser, with formulas.
git clone https://git.vogt.world/spreadsheet.git
Log | Files | README.md
← Commit log
commit
message
Added Formulas.COMBIN
author
Ben Vogt <[email protected]>
date
2017-02-20 18:02:49
stats
3 file(s) changed, 78 insertions(+), 2 deletions(-)
files
README.md
src/RawFormulas/RawFormulas.ts
tests/FormulasTest.ts
  1diff --git a/README.md b/README.md
  2index 1eace99..3b16fe2 100644
  3--- a/README.md
  4+++ b/README.md
  5@@ -32,4 +32,16 @@ arbitrary javascript is executed in the client machine.
  6 * ...etc.
  7 
  8 ### Refactor the way we construct and throw errors
  9-For example, the mis-matched argument length errors are all generated the same way.
 10\ No newline at end of file
 11+For example, the mis-matched argument length errors are all generated the same way.
 12+
 13+### Refactor the way tests are organized.
 14+Group by error type and have some useful functions that will call with 0, N, N+1 args to test the args
 15+checker. Also, test for *all possible* errors that could be thrown, and *all possible types* that could be passed in.
 16+Another thing to think about would be throwing custom errors if an object is passed in.
 17+
 18+### DIV_ZERO Error
 19+This error is thrown every time we're about to divide by zero in a formula. There are definitely a couple formulas that
 20+don't check for this, and they should.
 21+
 22+### jStat functions should know their caller
 23+Either through `arguments`, or directly passed in like `mean("FORMULA", [10, 20, 30])`
 24diff --git a/src/RawFormulas/RawFormulas.ts b/src/RawFormulas/RawFormulas.ts
 25index 82f2adf..dd375f1 100644
 26--- a/src/RawFormulas/RawFormulas.ts
 27+++ b/src/RawFormulas/RawFormulas.ts
 28@@ -106,7 +106,6 @@ import {CellError, NUM_ERROR} from "../Errors"
 29 import * as ERRORS from "../Errors"
 30 
 31 var ACCRINT = Formula["ACCRINT"];
 32-var COMBIN = Formula["COMBIN"];
 33 var CONVERT = Formula["CONVERT"];
 34 var CUMIPMT = Formula["CUMIPMT"];
 35 var CUMPRINC = Formula["CUMPRINC"];
 36@@ -133,6 +132,44 @@ var __COMPLEX = {
 37 };
 38 var YEARFRAC = Formula["YEARFRAC"];
 39 
 40+
 41+/**
 42+ * Returns the number of ways to choose some number of objects from a pool of a given size of objects.
 43+ * @param values[0] n - The size of the pool of objects to choose from.
 44+ * @param values[1] k - The number of objects to choose.
 45+ * @returns {number} number of ways
 46+ * @constructor
 47+ */
 48+var COMBIN = function (...values) : number {
 49+  var MEMOIZED_FACT = [];
 50+  function fact(number) {
 51+    var n = Math.floor(number);
 52+    if (n === 0 || n === 1) {
 53+      return 1;
 54+    } else if (MEMOIZED_FACT[n] > 0) {
 55+      return MEMOIZED_FACT[n];
 56+    } else {
 57+      MEMOIZED_FACT[n] = fact(n - 1) * n;
 58+      return MEMOIZED_FACT[n];
 59+    }
 60+  }
 61+  ArgsChecker.checkLength(values, 2);
 62+  var n = TypeCaster.firstValueAsNumber(values[0]);
 63+  var c = TypeCaster.firstValueAsNumber(values[1]);
 64+  if (n < c) {
 65+    throw new CellError(ERRORS.NUM_ERROR, "Function COMBIN parameter 2 value is "
 66+        + c + ". It should be less than or equal to value of Function COMBIN parameter 1 with " + n + ".");
 67+  }
 68+  n = Math.floor(n);
 69+  c = Math.floor(c);
 70+  var div = fact(c) * fact(n - c);
 71+  if (div === 0) {
 72+    throw new CellError(ERRORS.DIV_ZERO_ERROR, "Evaluation of function COMBIN caused a divide by zero error.");
 73+  }
 74+  return fact(n) / div;
 75+};
 76+
 77+
 78 /**
 79  * Calculates r, the Pearson product-moment correlation coefficient of a dataset. Any text encountered in the arguments
 80  * will be ignored. CORREL is synonymous with PEARSON.
 81diff --git a/tests/FormulasTest.ts b/tests/FormulasTest.ts
 82index a9df7a4..a10646d 100644
 83--- a/tests/FormulasTest.ts
 84+++ b/tests/FormulasTest.ts
 85@@ -419,7 +419,33 @@ assertEquals(CODE(['a']), 97);
 86 assertEquals(CODE([['a'], 'p']), 97);
 87 
 88 
 89+// Test COMBIN
 90 assertEquals(COMBIN(4, 2), 6);
 91+assertEquals(COMBIN(4.999, 2.888), 6);
 92+assertEquals(COMBIN([4, "str"], [2]), 6);
 93+assertEquals(COMBIN(0, 0), 1);
 94+catchAndAssertEquals(function() {
 95+  COMBIN(2, "str");
 96+}, ERRORS.VALUE_ERROR);
 97+catchAndAssertEquals(function() {
 98+  COMBIN(2, []);
 99+}, ERRORS.REF_ERROR);
100+catchAndAssertEquals(function() {
101+  COMBIN(2, 4);
102+}, ERRORS.NUM_ERROR);
103+catchAndAssertEquals(function() {
104+  COMBIN(0, 1);
105+}, ERRORS.NUM_ERROR);
106+catchAndAssertEquals(function() {
107+  COMBIN();
108+}, ERRORS.NA_ERROR);
109+catchAndAssertEquals(function() {
110+  COMBIN(4);
111+}, ERRORS.NA_ERROR);
112+catchAndAssertEquals(function() {
113+  COMBIN(4, 2, 66);
114+}, ERRORS.NA_ERROR);
115+
116 
117 
118 // Test CONCATENATE