v0.0.482 mathext.Percentile
All checks were successful
Build Docker and Deploy / Run goext test-suite (push) Successful in 3m46s
All checks were successful
Build Docker and Deploy / Run goext test-suite (push) Successful in 3m46s
This commit is contained in:
@@ -1,6 +1,9 @@
|
||||
package mathext
|
||||
|
||||
import "gogs.mikescher.com/BlackForestBytes/goext/langext"
|
||||
import (
|
||||
"gogs.mikescher.com/BlackForestBytes/goext/exerr"
|
||||
"gogs.mikescher.com/BlackForestBytes/goext/langext"
|
||||
)
|
||||
|
||||
func Sum[T langext.NumberConstraint](v []T) T {
|
||||
total := T(0)
|
||||
@@ -41,3 +44,53 @@ func ArrMax[T langext.OrderedConstraint](v []T) T {
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
func MustPercentile[T langext.NumberConstraint](rawdata []T, percentile float64) T {
|
||||
v, err := Percentile(rawdata, percentile)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
func Percentile[T langext.NumberConstraint](rawdata []T, percentile float64) (T, error) {
|
||||
v, err := FloatPercentile(rawdata, percentile)
|
||||
if err != nil {
|
||||
return T(0), err
|
||||
}
|
||||
return T(v), nil
|
||||
|
||||
}
|
||||
|
||||
func FloatPercentile[T langext.NumberConstraint](rawdata []T, percentile float64) (float64, error) {
|
||||
if len(rawdata) == 0 {
|
||||
return 0, exerr.New(exerr.TypeAssert, "no data to calculate percentile").Any("percentile", percentile).Build()
|
||||
}
|
||||
|
||||
if percentile < 0 || percentile > 100 {
|
||||
return 0, exerr.New(exerr.TypeAssert, "percentile out of range").Any("percentile", percentile).Build()
|
||||
}
|
||||
|
||||
data := langext.ArrCopy(rawdata)
|
||||
langext.Sort(data)
|
||||
|
||||
idxFloat := float64(len(data)-1) * (percentile / float64(100))
|
||||
|
||||
idxInt := int(idxFloat)
|
||||
|
||||
// exact match on index
|
||||
if idxFloat == float64(idxInt) {
|
||||
return float64(data[idxInt]), nil
|
||||
}
|
||||
|
||||
// linear interpolation
|
||||
v1 := data[idxInt]
|
||||
v2 := data[idxInt+1]
|
||||
|
||||
weight := idxFloat - float64(idxInt)
|
||||
|
||||
valFloat := (float64(v1) * (1 - weight)) + (float64(v2) * weight)
|
||||
|
||||
return valFloat, nil
|
||||
|
||||
}
|
||||
|
Reference in New Issue
Block a user