ref #65, new formula functions: GAMMA.INV and GAMMAINV and format code

This commit is contained in:
xuri 2022-03-12 00:45:27 +08:00
parent 361611c23a
commit e1d660dda7
No known key found for this signature in database
GPG Key ID: BA5E5BB1C948EDF7
3 changed files with 96 additions and 1 deletions

71
calc.go
View File

@ -432,6 +432,8 @@ type formulaFuncs struct {
// GAMMA
// GAMMA.DIST
// GAMMADIST
// GAMMA.INV
// GAMMAINV
// GAMMALN
// GAUSS
// GCD
@ -6088,6 +6090,75 @@ func (fn *formulaFuncs) GAMMADIST(argsList *list.List) formulaArg {
return newNumberFormulaArg((1 / (math.Pow(beta.Number, alpha.Number) * math.Gamma(alpha.Number))) * math.Pow(x.Number, (alpha.Number-1)) * math.Exp(0-(x.Number/beta.Number)))
}
// gammainv returns the inverse of the Gamma distribution for the specified
// value.
func gammainv(probability, alpha, beta float64) float64 {
xLo, xHi := 0.0, alpha*beta*5
dx, x, xNew, result := 1024.0, 1.0, 1.0, 0.0
for i := 0; math.Abs(dx) > 8.88e-016 && i <= 256; i++ {
result = incompleteGamma(alpha, x/beta) / math.Gamma(alpha)
error := result - probability
if error == 0 {
dx = 0
} else if error < 0 {
xLo = x
} else {
xHi = x
}
pdf := (1 / (math.Pow(beta, alpha) * math.Gamma(alpha))) * math.Pow(x, (alpha-1)) * math.Exp(0-(x/beta))
if pdf != 0 {
dx = error / pdf
xNew = x - dx
}
if xNew < xLo || xNew > xHi || pdf == 0 {
xNew = (xLo + xHi) / 2
dx = xNew - x
}
x = xNew
}
return x
}
// GAMMAdotINV function returns the inverse of the Gamma Cumulative
// Distribution. The syntax of the function is:
//
// GAMMA.INV(probability,alpha,beta)
//
func (fn *formulaFuncs) GAMMAdotINV(argsList *list.List) formulaArg {
if argsList.Len() != 3 {
return newErrorFormulaArg(formulaErrorVALUE, "GAMMA.INV requires 3 arguments")
}
return fn.GAMMAINV(argsList)
}
// GAMMAINV function returns the inverse of the Gamma Cumulative Distribution.
// The syntax of the function is:
//
// GAMMAINV(probability,alpha,beta)
//
func (fn *formulaFuncs) GAMMAINV(argsList *list.List) formulaArg {
if argsList.Len() != 3 {
return newErrorFormulaArg(formulaErrorVALUE, "GAMMAINV requires 3 arguments")
}
var probability, alpha, beta formulaArg
if probability = argsList.Front().Value.(formulaArg).ToNumber(); probability.Type != ArgNumber {
return probability
}
if probability.Number < 0 || probability.Number >= 1 {
return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
}
if alpha = argsList.Front().Next().Value.(formulaArg).ToNumber(); alpha.Type != ArgNumber {
return alpha
}
if beta = argsList.Back().Value.(formulaArg).ToNumber(); beta.Type != ArgNumber {
return beta
}
if alpha.Number <= 0 || beta.Number <= 0 {
return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM)
}
return newNumberFormulaArg(gammainv(probability.Number, alpha.Number, beta.Number))
}
// GAMMALN function returns the natural logarithm of the Gamma Function, Γ
// (n). The syntax of the function is:
//

View File

@ -841,6 +841,12 @@ func TestCalcCellValue(t *testing.T) {
// GAMMADIST
"=GAMMADIST(6,3,2,FALSE)": "0.112020903827694",
"=GAMMADIST(6,3,2,TRUE)": "0.576809918873156",
// GAMMA.INV
"=GAMMA.INV(0.5,3,2)": "5.348120627447122",
"=GAMMA.INV(0.5,0.5,1)": "0.227468211559786",
// GAMMAINV
"=GAMMAINV(0.5,3,2)": "5.348120627447122",
"=GAMMAINV(0.5,0.5,1)": "0.227468211559786",
// GAMMALN
"=GAMMALN(4.5)": "2.45373657084244",
"=GAMMALN(INT(1))": "0",
@ -2406,6 +2412,24 @@ func TestCalcCellValue(t *testing.T) {
"=GAMMADIST(-1,3,2,FALSE)": "#NUM!",
"=GAMMADIST(6,0,2,FALSE)": "#NUM!",
"=GAMMADIST(6,3,0,FALSE)": "#NUM!",
// GAMMA.INV
"=GAMMA.INV()": "GAMMA.INV requires 3 arguments",
"=GAMMA.INV(\"\",3,2)": "strconv.ParseFloat: parsing \"\": invalid syntax",
"=GAMMA.INV(0.5,\"\",2)": "strconv.ParseFloat: parsing \"\": invalid syntax",
"=GAMMA.INV(0.5,3,\"\")": "strconv.ParseFloat: parsing \"\": invalid syntax",
"=GAMMA.INV(-1,3,2)": "#NUM!",
"=GAMMA.INV(2,3,2)": "#NUM!",
"=GAMMA.INV(0.5,0,2)": "#NUM!",
"=GAMMA.INV(0.5,3,0)": "#NUM!",
// GAMMAINV
"=GAMMAINV()": "GAMMAINV requires 3 arguments",
"=GAMMAINV(\"\",3,2)": "strconv.ParseFloat: parsing \"\": invalid syntax",
"=GAMMAINV(0.5,\"\",2)": "strconv.ParseFloat: parsing \"\": invalid syntax",
"=GAMMAINV(0.5,3,\"\")": "strconv.ParseFloat: parsing \"\": invalid syntax",
"=GAMMAINV(-1,3,2)": "#NUM!",
"=GAMMAINV(2,3,2)": "#NUM!",
"=GAMMAINV(0.5,0,2)": "#NUM!",
"=GAMMAINV(0.5,3,0)": "#NUM!",
// GAMMALN
"=GAMMALN()": "GAMMALN requires 1 numeric argument",
"=GAMMALN(F1)": "GAMMALN requires 1 numeric argument",

View File

@ -514,7 +514,7 @@ func (f *File) drawBaseChart(formatSet *formatChart) *cPlotArea {
// doughnut chart by given format sets.
func (f *File) drawDoughnutChart(formatSet *formatChart) *cPlotArea {
holeSize := 75
if formatSet.HoleSize > 0 && formatSet.HoleSize <= 90{
if formatSet.HoleSize > 0 && formatSet.HoleSize <= 90 {
holeSize = formatSet.HoleSize
}