summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--calc.go90
-rw-r--r--calc_test.go23
2 files changed, 113 insertions, 0 deletions
diff --git a/calc.go b/calc.go
index 5bad72a..6252363 100644
--- a/calc.go
+++ b/calc.go
@@ -657,6 +657,8 @@ type formulaFuncs struct {
// TBILLEQ
// TBILLPRICE
// TBILLYIELD
+// T.DIST
+// TDIST
// TEXTJOIN
// TIME
// TIMEVALUE
@@ -9008,6 +9010,94 @@ func (fn *formulaFuncs) STDEVdotP(argsList *list.List) formulaArg {
return fn.stdevp("STDEV.P", argsList)
}
+// getTDist is an implementation for the beta distribution probability density
+// function.
+func getTDist(T, fDF, nType float64) float64 {
+ var res float64
+ switch nType {
+ case 1:
+ res = 0.5 * getBetaDist(fDF/(fDF+T*T), fDF/2, 0.5)
+ break
+ case 2:
+ res = getBetaDist(fDF/(fDF+T*T), fDF/2, 0.5)
+ break
+ case 3:
+ res = math.Pow(1+(T*T/fDF), -(fDF+1)/2) / (math.Sqrt(fDF) * getBeta(0.5, fDF/2.0))
+ break
+ case 4:
+ X := fDF / (T*T + fDF)
+ R := 0.5 * getBetaDist(X, 0.5*fDF, 0.5)
+ res = 1 - R
+ if T < 0 {
+ res = R
+ }
+ break
+ }
+ return res
+}
+
+// TdotDIST function calculates the one-tailed Student's T Distribution, which
+// is a continuous probability distribution that is frequently used for
+// testing hypotheses on small sample data sets. The syntax of the function
+// is:
+//
+// T.DIST(x,degrees_freedom,cumulative)
+//
+func (fn *formulaFuncs) TdotDIST(argsList *list.List) formulaArg {
+ if argsList.Len() != 3 {
+ return newErrorFormulaArg(formulaErrorVALUE, "T.DIST requires 3 arguments")
+ }
+ var x, degrees, cumulative formulaArg
+ if x = argsList.Front().Value.(formulaArg).ToNumber(); x.Type != ArgNumber {
+ return x
+ }
+ if degrees = argsList.Front().Next().Value.(formulaArg).ToNumber(); degrees.Type != ArgNumber {
+ return degrees
+ }
+ if cumulative = argsList.Back().Value.(formulaArg).ToBool(); cumulative.Type != ArgNumber {
+ return cumulative
+ }
+ if cumulative.Number == 1 && degrees.Number < 1 {
+ return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
+ }
+ if cumulative.Number == 0 {
+ if degrees.Number < 0 {
+ return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
+ }
+ if degrees.Number == 0 {
+ return newErrorFormulaArg(formulaErrorDIV, formulaErrorDIV)
+ }
+ return newNumberFormulaArg(getTDist(x.Number, degrees.Number, 3))
+ }
+ return newNumberFormulaArg(getTDist(x.Number, degrees.Number, 4))
+}
+
+// TDIST function calculates the Student's T Distribution, which is a
+// continuous probability distribution that is frequently used for testing
+// hypotheses on small sample data sets. The syntax of the function is:
+//
+// TDIST(x,degrees_freedom,tails)
+//
+func (fn *formulaFuncs) TDIST(argsList *list.List) formulaArg {
+ if argsList.Len() != 3 {
+ return newErrorFormulaArg(formulaErrorVALUE, "TDIST requires 3 arguments")
+ }
+ var x, degrees, tails formulaArg
+ if x = argsList.Front().Value.(formulaArg).ToNumber(); x.Type != ArgNumber {
+ return x
+ }
+ if degrees = argsList.Front().Next().Value.(formulaArg).ToNumber(); degrees.Type != ArgNumber {
+ return degrees
+ }
+ if tails = argsList.Back().Value.(formulaArg).ToNumber(); tails.Type != ArgNumber {
+ return tails
+ }
+ if x.Number < 0 || degrees.Number < 1 || (tails.Number != 1 && tails.Number != 2) {
+ return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
+ }
+ return newNumberFormulaArg(getTDist(x.Number, degrees.Number, tails.Number))
+}
+
// TRIMMEAN function calculates the trimmed mean (or truncated mean) of a
// supplied set of values. The syntax of the function is:
//
diff --git a/calc_test.go b/calc_test.go
index 2b76ed3..321934f 100644
--- a/calc_test.go
+++ b/calc_test.go
@@ -1155,6 +1155,13 @@ func TestCalcCellValue(t *testing.T) {
"=STDEVP(A1:B2,6,-1)": "2.40947204913349",
// STDEV.P
"=STDEV.P(A1:B2,6,-1)": "2.40947204913349",
+ // T.DIST
+ "=T.DIST(1,10,TRUE)": "0.82955343384897",
+ "=T.DIST(-1,10,TRUE)": "0.17044656615103",
+ "=T.DIST(-1,10,FALSE)": "0.230361989229139",
+ // TDIST
+ "=TDIST(1,10,1)": "0.17044656615103",
+ "=TDIST(1,10,2)": "0.34089313230206",
// TRIMMEAN
"=TRIMMEAN(A1:B4,10%)": "2.5",
"=TRIMMEAN(A1:B4,70%)": "2.5",
@@ -3009,6 +3016,22 @@ func TestCalcCellValue(t *testing.T) {
// STDEV.P
"=STDEV.P()": "STDEV.P requires at least 1 argument",
"=STDEV.P(\"\")": "#DIV/0!",
+ // T.DIST
+ "=T.DIST()": "T.DIST requires 3 arguments",
+ "=T.DIST(\"\",10,TRUE)": "strconv.ParseFloat: parsing \"\": invalid syntax",
+ "=T.DIST(1,\"\",TRUE)": "strconv.ParseFloat: parsing \"\": invalid syntax",
+ "=T.DIST(1,10,\"\")": "strconv.ParseBool: parsing \"\": invalid syntax",
+ "=T.DIST(1,0,TRUE)": "#NUM!",
+ "=T.DIST(1,-1,FALSE)": "#NUM!",
+ "=T.DIST(1,0,FALSE)": "#DIV/0!",
+ // TDIST
+ "=TDIST()": "TDIST requires 3 arguments",
+ "=TDIST(\"\",10,1)": "strconv.ParseFloat: parsing \"\": invalid syntax",
+ "=TDIST(1,\"\",1)": "strconv.ParseFloat: parsing \"\": invalid syntax",
+ "=TDIST(1,10,\"\")": "strconv.ParseFloat: parsing \"\": invalid syntax",
+ "=TDIST(-1,10,1)": "#NUM!",
+ "=TDIST(1,0,1)": "#NUM!",
+ "=TDIST(1,10,0)": "#NUM!",
// TRIMMEAN
"=TRIMMEAN()": "TRIMMEAN requires 2 arguments",
"=TRIMMEAN(A1,\"\")": "strconv.ParseFloat: parsing \"\": invalid syntax",