From 1ba3690764e90aa6f7bcb3cb1e095475d40e3d91 Mon Sep 17 00:00:00 2001 From: xuri Date: Tue, 14 Sep 2021 22:23:12 +0800 Subject: new formula functions: WEIBULL and WEIBULL.DIST, ref #65 --- calc.go | 42 ++++++++++++++++++++++++++++++++++++++++++ calc_test.go | 40 ++++++++++++++++++++++++++++------------ 2 files changed, 70 insertions(+), 12 deletions(-) diff --git a/calc.go b/calc.go index fa6ec0a..9cbc8ec 100644 --- a/calc.go +++ b/calc.go @@ -504,6 +504,8 @@ type formulaFuncs struct { // VAR.P // VARP // VLOOKUP +// WEIBULL +// WEIBULL.DIST // XOR // YEAR // Z.TEST @@ -5614,6 +5616,46 @@ func (fn *formulaFuncs) VARdotP(argsList *list.List) formulaArg { return fn.VARP(argsList) } +// WEIBULL function calculates the Weibull Probability Density Function or the +// Weibull Cumulative Distribution Function for a supplied set of parameters. +// The syntax of the function is: +// +// WEIBULL(x,alpha,beta,cumulative) +// +func (fn *formulaFuncs) WEIBULL(argsList *list.List) formulaArg { + if argsList.Len() != 4 { + return newErrorFormulaArg(formulaErrorVALUE, "WEIBULL requires 4 arguments") + } + x := argsList.Front().Value.(formulaArg).ToNumber() + alpha := argsList.Front().Next().Value.(formulaArg).ToNumber() + beta := argsList.Back().Prev().Value.(formulaArg).ToNumber() + if alpha.Type == ArgNumber && beta.Type == ArgNumber && x.Type == ArgNumber { + if alpha.Number < 0 || alpha.Number <= 0 || beta.Number <= 0 { + return newErrorFormulaArg(formulaErrorNA, formulaErrorNA) + } + cumulative := argsList.Back().Value.(formulaArg).ToBool() + if cumulative.Boolean && cumulative.Number == 1 { + return newNumberFormulaArg(1 - math.Exp(0-math.Pow((x.Number/beta.Number), alpha.Number))) + } + return newNumberFormulaArg((alpha.Number / math.Pow(beta.Number, alpha.Number)) * + math.Pow(x.Number, (alpha.Number-1)) * math.Exp(0-math.Pow((x.Number/beta.Number), alpha.Number))) + } + return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE) +} + +// WEIBULLdotDIST function calculates the Weibull Probability Density Function +// or the Weibull Cumulative Distribution Function for a supplied set of +// parameters. The syntax of the function is: +// +// WEIBULL.DIST(x,alpha,beta,cumulative) +// +func (fn *formulaFuncs) WEIBULLdotDIST(argsList *list.List) formulaArg { + if argsList.Len() != 4 { + return newErrorFormulaArg(formulaErrorVALUE, "WEIBULL.DIST requires 4 arguments") + } + return fn.WEIBULL(argsList) +} + // ZdotTEST function calculates the one-tailed probability value of the // Z-Test. The syntax of the function is: // diff --git a/calc_test.go b/calc_test.go index 7018ee9..763ea1f 100644 --- a/calc_test.go +++ b/calc_test.go @@ -858,6 +858,12 @@ func TestCalcCellValue(t *testing.T) { "=VARP(A1:A5)": "1.25", // VAR.P "=VAR.P(A1:A5)": "1.25", + // WEIBULL + "=WEIBULL(1,3,1,FALSE)": "1.103638323514327", + "=WEIBULL(2,5,1.5,TRUE)": "0.985212776817482", + // WEIBULL.DIST + "=WEIBULL.DIST(1,3,1,FALSE)": "1.103638323514327", + "=WEIBULL.DIST(2,5,1.5,TRUE)": "0.985212776817482", // Information Functions // ISBLANK "=ISBLANK(A1)": "FALSE", @@ -1899,20 +1905,30 @@ func TestCalcCellValue(t *testing.T) { // VAR.P "=VAR.P()": "VAR.P requires at least 1 argument", "=VAR.P(\"\")": "#DIV/0!", + // WEIBULL + "=WEIBULL()": "WEIBULL requires 4 arguments", + "=WEIBULL(\"\",1,1,FALSE)": "#VALUE!", + "=WEIBULL(1,0,1,FALSE)": "#N/A", + "=WEIBULL(1,1,-1,FALSE)": "#N/A", + // WEIBULL.DIST + "=WEIBULL.DIST()": "WEIBULL.DIST requires 4 arguments", + "=WEIBULL.DIST(\"\",1,1,FALSE)": "#VALUE!", + "=WEIBULL.DIST(1,0,1,FALSE)": "#N/A", + "=WEIBULL.DIST(1,1,-1,FALSE)": "#N/A", // Z.TEST - "Z.TEST(A1)": "Z.TEST requires at least 2 arguments", - "Z.TEST(A1,0,0,0)": "Z.TEST accepts at most 3 arguments", - "Z.TEST(H1,0)": "#N/A", - "Z.TEST(A1,\"\")": "strconv.ParseFloat: parsing \"\": invalid syntax", - "Z.TEST(A1,1)": "#DIV/0!", - "Z.TEST(A1,1,\"\")": "strconv.ParseFloat: parsing \"\": invalid syntax", + "=Z.TEST(A1)": "Z.TEST requires at least 2 arguments", + "=Z.TEST(A1,0,0,0)": "Z.TEST accepts at most 3 arguments", + "=Z.TEST(H1,0)": "#N/A", + "=Z.TEST(A1,\"\")": "strconv.ParseFloat: parsing \"\": invalid syntax", + "=Z.TEST(A1,1)": "#DIV/0!", + "=Z.TEST(A1,1,\"\")": "strconv.ParseFloat: parsing \"\": invalid syntax", // ZTEST - "ZTEST(A1)": "ZTEST requires at least 2 arguments", - "ZTEST(A1,0,0,0)": "ZTEST accepts at most 3 arguments", - "ZTEST(H1,0)": "#N/A", - "ZTEST(A1,\"\")": "strconv.ParseFloat: parsing \"\": invalid syntax", - "ZTEST(A1,1)": "#DIV/0!", - "ZTEST(A1,1,\"\")": "strconv.ParseFloat: parsing \"\": invalid syntax", + "=ZTEST(A1)": "ZTEST requires at least 2 arguments", + "=ZTEST(A1,0,0,0)": "ZTEST accepts at most 3 arguments", + "=ZTEST(H1,0)": "#N/A", + "=ZTEST(A1,\"\")": "strconv.ParseFloat: parsing \"\": invalid syntax", + "=ZTEST(A1,1)": "#DIV/0!", + "=ZTEST(A1,1,\"\")": "strconv.ParseFloat: parsing \"\": invalid syntax", // Information Functions // ISBLANK "=ISBLANK(A1,A2)": "ISBLANK requires 1 argument", -- cgit v1.2.1