summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--calc.go63
-rw-r--r--calc_test.go29
2 files changed, 92 insertions, 0 deletions
diff --git a/calc.go b/calc.go
index f279b34..5bad72a 100644
--- a/calc.go
+++ b/calc.go
@@ -555,6 +555,8 @@ type formulaFuncs struct {
// MUNIT
// N
// NA
+// NEGBINOM.DIST
+// NEGBINOMDIST
// NOMINAL
// NORM.DIST
// NORMDIST
@@ -7983,6 +7985,67 @@ func (fn *formulaFuncs) LOGNORMDIST(argsList *list.List) formulaArg {
return fn.NORMSDIST(args)
}
+// 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
+// before a required number of successes is achieved. The syntax of the
+// function is:
+//
+// NEGBINOM.DIST(number_f,number_s,probability_s,cumulative)
+//
+func (fn *formulaFuncs) NEGBINOMdotDIST(argsList *list.List) formulaArg {
+ if argsList.Len() != 4 {
+ return newErrorFormulaArg(formulaErrorVALUE, "NEGBINOM.DIST requires 4 arguments")
+ }
+ var f, s, probability, cumulative formulaArg
+ if f = argsList.Front().Value.(formulaArg).ToNumber(); f.Type != ArgNumber {
+ return f
+ }
+ if s = argsList.Front().Next().Value.(formulaArg).ToNumber(); s.Type != ArgNumber {
+ return s
+ }
+ if probability = argsList.Front().Next().Next().Value.(formulaArg).ToNumber(); probability.Type != ArgNumber {
+ return probability
+ }
+ if cumulative = argsList.Back().Value.(formulaArg).ToBool(); cumulative.Type != ArgNumber {
+ return cumulative
+ }
+ if f.Number < 0 || s.Number < 1 || probability.Number < 0 || probability.Number > 1 {
+ return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
+ }
+ if cumulative.Number == 1 {
+ return newNumberFormulaArg(1 - getBetaDist(1-probability.Number, f.Number+1, s.Number))
+ }
+ return newNumberFormulaArg(binomCoeff(f.Number+s.Number-1, s.Number-1) * math.Pow(probability.Number, s.Number) * math.Pow(1-probability.Number, f.Number))
+}
+
+// NEGBINOMDIST function calculates the Negative Binomial Distribution for a
+// given set of parameters. This gives the probability that there will be a
+// specified number of failures before a required number of successes is
+// achieved. The syntax of the function is:
+//
+// NEGBINOMDIST(number_f,number_s,probability_s)
+//
+func (fn *formulaFuncs) NEGBINOMDIST(argsList *list.List) formulaArg {
+ if argsList.Len() != 3 {
+ return newErrorFormulaArg(formulaErrorVALUE, "NEGBINOMDIST requires 3 arguments")
+ }
+ var f, s, probability formulaArg
+ if f = argsList.Front().Value.(formulaArg).ToNumber(); f.Type != ArgNumber {
+ return f
+ }
+ if s = argsList.Front().Next().Value.(formulaArg).ToNumber(); s.Type != ArgNumber {
+ return s
+ }
+ if probability = argsList.Back().Value.(formulaArg).ToNumber(); probability.Type != ArgNumber {
+ return probability
+ }
+ if f.Number < 0 || s.Number < 1 || probability.Number < 0 || probability.Number > 1 {
+ return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
+ }
+ return newNumberFormulaArg(binomCoeff(f.Number+s.Number-1, s.Number-1) * math.Pow(probability.Number, s.Number) * math.Pow(1-probability.Number, f.Number))
+}
+
// NORMdotDIST function calculates the Normal Probability Density Function or
// the Cumulative Normal Distribution. Function for a supplied set of
// parameters. The syntax of the function is:
diff --git a/calc_test.go b/calc_test.go
index 43f6a29..2b76ed3 100644
--- a/calc_test.go
+++ b/calc_test.go
@@ -1015,6 +1015,16 @@ func TestCalcCellValue(t *testing.T) {
"=LOGNORM.DIST(12,10,5,TRUE)": "0.0664171147992078",
// LOGNORMDIST
"=LOGNORMDIST(12,10,5)": "0.0664171147992078",
+ // NEGBINOM.DIST
+ "=NEGBINOM.DIST(6,12,0.5,FALSE)": "0.047210693359375",
+ "=NEGBINOM.DIST(12,12,0.5,FALSE)": "0.0805901288986206",
+ "=NEGBINOM.DIST(15,12,0.5,FALSE)": "0.057564377784729",
+ "=NEGBINOM.DIST(12,12,0.5,TRUE)": "0.580590128898621",
+ "=NEGBINOM.DIST(15,12,0.5,TRUE)": "0.778965830802917",
+ // NEGBINOMDIST
+ "=NEGBINOMDIST(6,12,0.5)": "0.047210693359375",
+ "=NEGBINOMDIST(12,12,0.5)": "0.0805901288986206",
+ "=NEGBINOMDIST(15,12,0.5)": "0.057564377784729",
// NORM.DIST
"=NORM.DIST(0.8,1,0.3,TRUE)": "0.252492537546923",
"=NORM.DIST(50,40,20,FALSE)": "0.017603266338215",
@@ -2835,6 +2845,25 @@ func TestCalcCellValue(t *testing.T) {
"=LOGNORMDIST(12,10,\"\")": "strconv.ParseFloat: parsing \"\": invalid syntax",
"=LOGNORMDIST(0,2,5)": "#NUM!",
"=LOGNORMDIST(12,10,0)": "#NUM!",
+ // NEGBINOM.DIST
+ "=NEGBINOM.DIST()": "NEGBINOM.DIST requires 4 arguments",
+ "=NEGBINOM.DIST(\"\",12,0.5,TRUE)": "strconv.ParseFloat: parsing \"\": invalid syntax",
+ "=NEGBINOM.DIST(6,\"\",0.5,TRUE)": "strconv.ParseFloat: parsing \"\": invalid syntax",
+ "=NEGBINOM.DIST(6,12,\"\",TRUE)": "strconv.ParseFloat: parsing \"\": invalid syntax",
+ "=NEGBINOM.DIST(6,12,0.5,\"\")": "strconv.ParseBool: parsing \"\": invalid syntax",
+ "=NEGBINOM.DIST(-1,12,0.5,TRUE)": "#NUM!",
+ "=NEGBINOM.DIST(6,0,0.5,TRUE)": "#NUM!",
+ "=NEGBINOM.DIST(6,12,-1,TRUE)": "#NUM!",
+ "=NEGBINOM.DIST(6,12,2,TRUE)": "#NUM!",
+ // NEGBINOMDIST
+ "=NEGBINOMDIST()": "NEGBINOMDIST requires 3 arguments",
+ "=NEGBINOMDIST(\"\",12,0.5)": "strconv.ParseFloat: parsing \"\": invalid syntax",
+ "=NEGBINOMDIST(6,\"\",0.5)": "strconv.ParseFloat: parsing \"\": invalid syntax",
+ "=NEGBINOMDIST(6,12,\"\")": "strconv.ParseFloat: parsing \"\": invalid syntax",
+ "=NEGBINOMDIST(-1,12,0.5)": "#NUM!",
+ "=NEGBINOMDIST(6,0,0.5)": "#NUM!",
+ "=NEGBINOMDIST(6,12,-1)": "#NUM!",
+ "=NEGBINOMDIST(6,12,2)": "#NUM!",
// NORM.DIST
"=NORM.DIST()": "NORM.DIST requires 4 arguments",
// NORMDIST