summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--calc.go77
-rw-r--r--calc_test.go24
2 files changed, 83 insertions, 18 deletions
diff --git a/calc.go b/calc.go
index f4f6b0c..657670c 100644
--- a/calc.go
+++ b/calc.go
@@ -572,8 +572,11 @@ type formulaFuncs struct {
// UNICODE
// UPPER
// VALUE
+// VAR
// VAR.P
+// VARA
// VARP
+// VARPA
// VLOOKUP
// WEEKDAY
// WEIBULL
@@ -6098,43 +6101,89 @@ func (fn *formulaFuncs) TRIMMEAN(argsList *list.List) formulaArg {
return fn.AVERAGE(args)
}
-// VARP function returns the Variance of a given set of values. The syntax of
-// the function is:
-//
-// VARP(number1,[number2],...)
-//
-func (fn *formulaFuncs) VARP(argsList *list.List) formulaArg {
+// vars is an implementation of the formula functions VAR, VARA, VARP, VAR.P
+// and VARPA.
+func (fn *formulaFuncs) vars(name string, argsList *list.List) formulaArg {
if argsList.Len() < 1 {
- return newErrorFormulaArg(formulaErrorVALUE, "VARP requires at least 1 argument")
+ return newErrorFormulaArg(formulaErrorVALUE, fmt.Sprintf("%s requires at least 1 argument", name))
}
summerA, summerB, count := 0.0, 0.0, 0.0
+ minimum := 0.0
+ if name == "VAR" || name == "VARA" {
+ minimum = 1.0
+ }
for arg := argsList.Front(); arg != nil; arg = arg.Next() {
for _, token := range arg.Value.(formulaArg).ToList() {
- if num := token.ToNumber(); num.Type == ArgNumber {
+ num := token.ToNumber()
+ if token.Value() != "TRUE" && num.Type == ArgNumber {
+ summerA += (num.Number * num.Number)
+ summerB += num.Number
+ count++
+ continue
+ }
+ num = token.ToBool()
+ if num.Type == ArgNumber {
summerA += (num.Number * num.Number)
summerB += num.Number
count++
+ continue
+ }
+ if name == "VARA" || name == "VARPA" {
+ count++
}
}
}
- if count > 0 {
+ if count > minimum {
summerA *= count
summerB *= summerB
- return newNumberFormulaArg((summerA - summerB) / (count * count))
+ return newNumberFormulaArg((summerA - summerB) / (count * (count - minimum)))
}
return newErrorFormulaArg(formulaErrorDIV, formulaErrorDIV)
}
+// VAR function returns the sample variance of a supplied set of values. The
+// syntax of the function is:
+//
+// VAR(number1,[number2],...)
+//
+func (fn *formulaFuncs) VAR(argsList *list.List) formulaArg {
+ return fn.vars("VAR", argsList)
+}
+
+// VARA function calculates the sample variance of a supplied set of values.
+// The syntax of the function is:
+//
+// VARA(number1,[number2],...)
+//
+func (fn *formulaFuncs) VARA(argsList *list.List) formulaArg {
+ return fn.vars("VARA", argsList)
+}
+
+// VARP function returns the Variance of a given set of values. The syntax of
+// the function is:
+//
+// VARP(number1,[number2],...)
+//
+func (fn *formulaFuncs) VARP(argsList *list.List) formulaArg {
+ return fn.vars("VARP", argsList)
+}
+
// VARdotP function returns the Variance of a given set of values. The syntax
// of the function is:
//
// VAR.P(number1,[number2],...)
//
func (fn *formulaFuncs) VARdotP(argsList *list.List) formulaArg {
- if argsList.Len() < 1 {
- return newErrorFormulaArg(formulaErrorVALUE, "VAR.P requires at least 1 argument")
- }
- return fn.VARP(argsList)
+ return fn.vars("VAR.P", argsList)
+}
+
+// VARPA function returns the Variance of a given set of values. The syntax of
+// the function is:
+//
+// VARPA(number1,[number2],...)
+//
+func (fn *formulaFuncs) VARPA(argsList *list.List) formulaArg {
+ return fn.vars("VARPA", argsList)
}
// WEIBULL function calculates the Weibull Probability Density Function or the
diff --git a/calc_test.go b/calc_test.go
index a2ac719..46f4f08 100644
--- a/calc_test.go
+++ b/calc_test.go
@@ -912,9 +912,9 @@ func TestCalcCellValue(t *testing.T) {
"=SMALL(A1,1)": "1",
"=SMALL(A1:F2,1)": "1",
// STANDARDIZE
- "=STANDARDIZE( 5.5, 5, 2 )": "0.25",
- "=STANDARDIZE( 12, 15, 1.5 )": "-2",
- "=STANDARDIZE( -2, 0, 5 )": "-0.4",
+ "=STANDARDIZE(5.5,5,2)": "0.25",
+ "=STANDARDIZE(12,15,1.5)": "-2",
+ "=STANDARDIZE(-2,0,5)": "-0.4",
// STDEVP
"=STDEVP(A1:B2,6,-1)": "2.40947204913349",
// STDEV.P
@@ -922,10 +922,20 @@ func TestCalcCellValue(t *testing.T) {
// TRIMMEAN
"=TRIMMEAN(A1:B4,10%)": "2.5",
"=TRIMMEAN(A1:B4,70%)": "2.5",
+ // VAR
+ "=VAR(1,3,5,0,C1)": "4.916666666666667",
+ "=VAR(1,3,5,0,C1,TRUE)": "4",
+ // VARA
+ "=VARA(1,3,5,0,C1)": "4.7",
+ "=VARA(1,3,5,0,C1,TRUE)": "3.86666666666667",
// VARP
- "=VARP(A1:A5)": "1.25",
+ "=VARP(A1:A5)": "1.25",
+ "=VARP(1,3,5,0,C1,TRUE)": "3.2",
// VAR.P
"=VAR.P(A1:A5)": "1.25",
+ // VARPA
+ "=VARPA(1,3,5,0,C1)": "3.76",
+ "=VARPA(1,3,5,0,C1,TRUE)": "3.22222222222222",
// WEIBULL
"=WEIBULL(1,3,1,FALSE)": "1.103638323514327",
"=WEIBULL(2,5,1.5,TRUE)": "0.985212776817482",
@@ -2191,12 +2201,18 @@ func TestCalcCellValue(t *testing.T) {
"=TRIMMEAN(A1,\"\")": "strconv.ParseFloat: parsing \"\": invalid syntax",
"=TRIMMEAN(A1,1)": "#NUM!",
"=TRIMMEAN(A1,-1)": "#NUM!",
+ // VAR
+ "=VAR()": "VAR requires at least 1 argument",
+ // VARA
+ "=VARA()": "VARA requires at least 1 argument",
// VARP
"=VARP()": "VARP requires at least 1 argument",
"=VARP(\"\")": "#DIV/0!",
// VAR.P
"=VAR.P()": "VAR.P requires at least 1 argument",
"=VAR.P(\"\")": "#DIV/0!",
+ // VARPA
+ "=VARPA()": "VARPA requires at least 1 argument",
// WEIBULL
"=WEIBULL()": "WEIBULL requires 4 arguments",
"=WEIBULL(\"\",1,1,FALSE)": "#VALUE!",