summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorxuri <xuri.me@gmail.com>2022-04-07 08:16:55 +0800
committerxuri <xuri.me@gmail.com>2022-04-07 08:16:55 +0800
commit9b8f1a15e1b75f56d9305b49212ee34ec085943f (patch)
tree99d1a7236f184eada699f34840881048b39880dc
parent5bf4bce9d41b2f8cd9d24e0d57a0d6868ef9433d (diff)
ref #65, new formula functions: MODE.MULT and MODE.SNGL
-rw-r--r--calc.go63
-rw-r--r--calc_test.go19
2 files changed, 77 insertions, 5 deletions
diff --git a/calc.go b/calc.go
index d921c35..20d5b5e 100644
--- a/calc.go
+++ b/calc.go
@@ -550,6 +550,8 @@ type formulaFuncs struct {
// MIRR
// MOD
// MODE
+// MODE.MULT
+// MODE.SNGL
// MONTH
// MROUND
// MULTINOMIAL
@@ -8021,6 +8023,67 @@ func (fn *formulaFuncs) MODE(argsList *list.List) formulaArg {
return newNumberFormulaArg(mode)
}
+// MODEdotMULT function returns a vertical array of the statistical modes
+// (the most frequently occurring values) within a list of supplied numbers.
+// The syntax of the function is:
+//
+// MODE.MULT(number1,[number2],...)
+//
+func (fn *formulaFuncs) MODEdotMULT(argsList *list.List) formulaArg {
+ if argsList.Len() < 1 {
+ return newErrorFormulaArg(formulaErrorVALUE, "MODE.MULT requires at least 1 argument")
+ }
+ var values []float64
+ for arg := argsList.Front(); arg != nil; arg = arg.Next() {
+ cells := arg.Value.(formulaArg)
+ if cells.Type != ArgMatrix && cells.ToNumber().Type != ArgNumber {
+ return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE)
+ }
+ for _, cell := range cells.ToList() {
+ if num := cell.ToNumber(); num.Type == ArgNumber {
+ values = append(values, num.Number)
+ }
+ }
+ }
+ sort.Float64s(values)
+ cnt := len(values)
+ var count, modeCnt int
+ var mtx [][]formulaArg
+ for i := 0; i < cnt; i++ {
+ count = 0
+ for j := i + 1; j < cnt; j++ {
+ if values[i] == values[j] {
+ count++
+ }
+ }
+ if count > modeCnt {
+ modeCnt = count
+ mtx = [][]formulaArg{}
+ mtx = append(mtx, []formulaArg{newNumberFormulaArg(values[i])})
+ } else if count == modeCnt {
+ mtx = append(mtx, []formulaArg{newNumberFormulaArg(values[i])})
+ }
+ }
+ if modeCnt == 0 {
+ return newErrorFormulaArg(formulaErrorNA, formulaErrorNA)
+ }
+ return newMatrixFormulaArg(mtx)
+}
+
+// MODEdotSNGL function returns the statistical mode (the most frequently
+// occurring value) within a list of supplied numbers. If there are 2 or more
+// most frequently occurring values in the supplied data, the function returns
+// the lowest of these values. The syntax of the function is:
+//
+// MODE.SNGL(number1,[number2],...)
+//
+func (fn *formulaFuncs) MODEdotSNGL(argsList *list.List) formulaArg {
+ if argsList.Len() < 1 {
+ return newErrorFormulaArg(formulaErrorVALUE, "MODE.SNGL requires at least 1 argument")
+ }
+ return fn.MODE(argsList)
+}
+
// NEGBINOMdotDIST function calculates the probability mass function or the
// cumulative distribution function for the Negative Binomial Distribution.
// This gives the probability that there will be a given number of failures
diff --git a/calc_test.go b/calc_test.go
index f6499de..689fd92 100644
--- a/calc_test.go
+++ b/calc_test.go
@@ -4880,8 +4880,11 @@ func TestCalcMODE(t *testing.T) {
}
f := prepareCalcData(cellData)
formulaList := map[string]string{
- "=MODE(A1:A10)": "3",
- "=MODE(B1:B6)": "2",
+ "=MODE(A1:A10)": "3",
+ "=MODE(B1:B6)": "2",
+ "=MODE.MULT(A1:A10)": "",
+ "=MODE.SNGL(A1:A10)": "3",
+ "=MODE.SNGL(B1:B6)": "2",
}
for formula, expected := range formulaList {
assert.NoError(t, f.SetCellFormula("Sheet1", "C1", formula))
@@ -4890,9 +4893,15 @@ func TestCalcMODE(t *testing.T) {
assert.Equal(t, expected, result, formula)
}
calcError := map[string]string{
- "=MODE()": "MODE requires at least 1 argument",
- "=MODE(0,\"\")": "#VALUE!",
- "=MODE(D1:D3)": "#N/A",
+ "=MODE()": "MODE requires at least 1 argument",
+ "=MODE(0,\"\")": "#VALUE!",
+ "=MODE(D1:D3)": "#N/A",
+ "=MODE.MULT()": "MODE.MULT requires at least 1 argument",
+ "=MODE.MULT(0,\"\")": "#VALUE!",
+ "=MODE.MULT(D1:D3)": "#N/A",
+ "=MODE.SNGL()": "MODE.SNGL requires at least 1 argument",
+ "=MODE.SNGL(0,\"\")": "#VALUE!",
+ "=MODE.SNGL(D1:D3)": "#N/A",
}
for formula, expected := range calcError {
assert.NoError(t, f.SetCellFormula("Sheet1", "C1", formula))