Executable
+44
@@ -0,0 +1,44 @@
|
||||
package maths
|
||||
|
||||
import "math"
|
||||
|
||||
func Correlation(data1, data2 Float64Data) (float64, error) {
|
||||
l1 := data1.Len()
|
||||
l2 := data2.Len()
|
||||
if l1 == 0 || l2 == 0 {
|
||||
return math.NaN(), EmptyInputErr
|
||||
}
|
||||
if l1 != l2 {
|
||||
return math.NaN(), SizeErr
|
||||
}
|
||||
sdev1, _ := StandardDeviationPopulation(data1)
|
||||
sdev2, _ := StandardDeviationPopulation(data2)
|
||||
if sdev1 == 0 || sdev2 == 0 {
|
||||
return 0, nil
|
||||
}
|
||||
covp, _ := CovariancePopulation(data1, data2)
|
||||
return covp / (sdev1 * sdev2), nil
|
||||
}
|
||||
|
||||
func Pearson(data1, data2 Float64Data) (float64, error) {
|
||||
return Correlation(data1, data2)
|
||||
}
|
||||
|
||||
func AutoCorrelation(data Float64Data, lags int) (float64, error) {
|
||||
if len(data) < 1 {
|
||||
return 0, EmptyInputErr
|
||||
}
|
||||
mean, _ := Mean(data)
|
||||
var result, q float64
|
||||
for i := 0; i < lags; i++ {
|
||||
v := (data[0] - mean) * (data[0] - mean)
|
||||
for i := 1; i < len(data); i++ {
|
||||
delta0 := data[i-1] - mean
|
||||
delta1 := data[i] - mean
|
||||
q += (delta0*delta1 - q) / float64(i+1)
|
||||
v += (delta1*delta1 - v) / float64(i+1)
|
||||
}
|
||||
result = q / v
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
Executable
+23
@@ -0,0 +1,23 @@
|
||||
package maths
|
||||
|
||||
type Float64Data []float64
|
||||
|
||||
func (f Float64Data) Get(i int) float64 { return f[i] }
|
||||
|
||||
func (f Float64Data) Len() int { return len(f) }
|
||||
|
||||
func (f Float64Data) Sum() (float64, error) { return Sum(f) }
|
||||
|
||||
func (f Float64Data) Mean() (float64, error) { return Mean(f) }
|
||||
|
||||
func (f Float64Data) Correlation(d Float64Data) (float64, error) {
|
||||
return Correlation(f, d)
|
||||
}
|
||||
|
||||
func (f Float64Data) AutoCorrelation(lags int) (float64, error) {
|
||||
return AutoCorrelation(f, lags)
|
||||
}
|
||||
|
||||
func (f Float64Data) Pearson(d Float64Data) (float64, error) {
|
||||
return Pearson(f, d)
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
package maths
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
"github.com/shopspring/decimal"
|
||||
)
|
||||
|
||||
// 保留2位小数
|
||||
func Decimal2Bit(value float64) float64 {
|
||||
data, _ := strconv.ParseFloat(fmt.Sprintf("%.2f", value), 64)
|
||||
return data
|
||||
}
|
||||
|
||||
// 保留4位小数
|
||||
func Decimal4Bit(value float64) float64 {
|
||||
data, _ := strconv.ParseFloat(fmt.Sprintf("%.4f", value), 64)
|
||||
return data
|
||||
}
|
||||
|
||||
// 保留6位小数
|
||||
func Decimal6Bit(value float64) float64 {
|
||||
data, _ := strconv.ParseFloat(fmt.Sprintf("%.6f", value), 64)
|
||||
return data
|
||||
}
|
||||
|
||||
// 相乘
|
||||
func DecimalMul(dec1, dec2 string) (string, error) {
|
||||
n1, err := decimal.NewFromString(dec1)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
n2, err := decimal.NewFromString(dec2)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return n1.Mul(n2).String(), nil
|
||||
}
|
||||
|
||||
// 相加
|
||||
func DecimalAdd(dec1, dec2 string) (string, error) {
|
||||
n1, err := decimal.NewFromString(dec1)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
n2, err := decimal.NewFromString(dec2)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return n1.Add(n2).String(), nil
|
||||
}
|
||||
|
||||
// 相除
|
||||
func DecimalDiv(dec1, dec2 string) (string, error) {
|
||||
n1, err := decimal.NewFromString(dec1)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
n2, err := decimal.NewFromString(dec2)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return n1.Div(n2).String(), nil
|
||||
}
|
||||
|
||||
// 相减
|
||||
func DecimalSub(dec1, dec2 string) (string, error) {
|
||||
n1, err := decimal.NewFromString(dec1)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
n2, err := decimal.NewFromString("-" + dec2)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return n1.Add(n2).String(), nil
|
||||
}
|
||||
Executable
+34
@@ -0,0 +1,34 @@
|
||||
package maths
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
func StandardDeviationPopulation(input Float64Data) (sdev float64, err error) {
|
||||
if input.Len() == 0 {
|
||||
return math.NaN(), EmptyInputErr
|
||||
}
|
||||
vp, _ := PopulationVariance(input)
|
||||
return math.Pow(vp, 0.5), nil
|
||||
}
|
||||
|
||||
func DivideInt64(a, b int64) float64 {
|
||||
if b == 0 {
|
||||
return 0
|
||||
}
|
||||
return float64(a) / float64(b)
|
||||
}
|
||||
|
||||
func DivideFloat64(a, b float64) float64 {
|
||||
if b == 0 {
|
||||
return 0
|
||||
}
|
||||
return a / b
|
||||
}
|
||||
|
||||
func ToFloat64_b2(v float64) float64 {
|
||||
f, _ := strconv.ParseFloat(fmt.Sprintf("%.2f", v), 64)
|
||||
return f
|
||||
}
|
||||
Executable
+31
@@ -0,0 +1,31 @@
|
||||
package maths
|
||||
|
||||
type statsError struct {
|
||||
err string
|
||||
}
|
||||
|
||||
func (s statsError) Error() string {
|
||||
return s.err
|
||||
}
|
||||
|
||||
func (s statsError) String() string {
|
||||
return s.err
|
||||
}
|
||||
|
||||
var (
|
||||
ErrEmptyInput = statsError{"Input must not be empty."}
|
||||
|
||||
ErrNaN = statsError{"Not a number."}
|
||||
|
||||
ErrNegative = statsError{"Must not contain negative values."}
|
||||
|
||||
ErrZero = statsError{"Must not contain zero values."}
|
||||
|
||||
ErrBounds = statsError{"Input is outside of range."}
|
||||
|
||||
ErrSize = statsError{"Must be the same length."}
|
||||
|
||||
ErrInfValue = statsError{"Value is infinite."}
|
||||
|
||||
ErrYCoord = statsError{"Y Value must be greater than zero."}
|
||||
)
|
||||
Executable
+17
@@ -0,0 +1,17 @@
|
||||
package maths
|
||||
|
||||
func VarP(input Float64Data) (sdev float64, err error) {
|
||||
return PopulationVariance(input)
|
||||
}
|
||||
|
||||
var (
|
||||
EmptyInputErr = ErrEmptyInput
|
||||
NaNErr = ErrNaN
|
||||
NegativeErr = ErrNegative
|
||||
ZeroErr = ErrZero
|
||||
BoundsErr = ErrBounds
|
||||
SizeErr = ErrSize
|
||||
InfValue = ErrInfValue
|
||||
YCoordErr = ErrYCoord
|
||||
EmptyInput = ErrEmptyInput
|
||||
)
|
||||
Executable
+181
@@ -0,0 +1,181 @@
|
||||
package maths
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
func LoadRawData(raw interface{}) (f Float64Data) {
|
||||
var r []interface{}
|
||||
var s Float64Data
|
||||
switch t := raw.(type) {
|
||||
case []interface{}:
|
||||
r = t
|
||||
case []uint:
|
||||
for _, v := range t {
|
||||
s = append(s, float64(v))
|
||||
}
|
||||
return s
|
||||
case []uint8:
|
||||
for _, v := range t {
|
||||
s = append(s, float64(v))
|
||||
}
|
||||
return s
|
||||
case []uint16:
|
||||
for _, v := range t {
|
||||
s = append(s, float64(v))
|
||||
}
|
||||
return s
|
||||
case []uint32:
|
||||
for _, v := range t {
|
||||
s = append(s, float64(v))
|
||||
}
|
||||
return s
|
||||
case []uint64:
|
||||
for _, v := range t {
|
||||
s = append(s, float64(v))
|
||||
}
|
||||
return s
|
||||
case []bool:
|
||||
for _, v := range t {
|
||||
if v {
|
||||
s = append(s, 1.0)
|
||||
} else {
|
||||
s = append(s, 0.0)
|
||||
}
|
||||
}
|
||||
return s
|
||||
case []float64:
|
||||
return Float64Data(t)
|
||||
case []int:
|
||||
for _, v := range t {
|
||||
s = append(s, float64(v))
|
||||
}
|
||||
return s
|
||||
case []int8:
|
||||
for _, v := range t {
|
||||
s = append(s, float64(v))
|
||||
}
|
||||
return s
|
||||
case []int16:
|
||||
for _, v := range t {
|
||||
s = append(s, float64(v))
|
||||
}
|
||||
return s
|
||||
case []int32:
|
||||
for _, v := range t {
|
||||
s = append(s, float64(v))
|
||||
}
|
||||
return s
|
||||
case []int64:
|
||||
for _, v := range t {
|
||||
s = append(s, float64(v))
|
||||
}
|
||||
return s
|
||||
case []string:
|
||||
for _, v := range t {
|
||||
r = append(r, v)
|
||||
}
|
||||
case []time.Duration:
|
||||
for _, v := range t {
|
||||
r = append(r, v)
|
||||
}
|
||||
case map[int]int:
|
||||
for i := 0; i < len(t); i++ {
|
||||
s = append(s, float64(t[i]))
|
||||
}
|
||||
return s
|
||||
case map[int]int8:
|
||||
for i := 0; i < len(t); i++ {
|
||||
s = append(s, float64(t[i]))
|
||||
}
|
||||
return s
|
||||
case map[int]int16:
|
||||
for i := 0; i < len(t); i++ {
|
||||
s = append(s, float64(t[i]))
|
||||
}
|
||||
return s
|
||||
case map[int]int32:
|
||||
for i := 0; i < len(t); i++ {
|
||||
s = append(s, float64(t[i]))
|
||||
}
|
||||
return s
|
||||
case map[int]int64:
|
||||
for i := 0; i < len(t); i++ {
|
||||
s = append(s, float64(t[i]))
|
||||
}
|
||||
return s
|
||||
case map[int]string:
|
||||
for i := 0; i < len(t); i++ {
|
||||
r = append(r, t[i])
|
||||
}
|
||||
case map[int]uint:
|
||||
for i := 0; i < len(t); i++ {
|
||||
s = append(s, float64(t[i]))
|
||||
}
|
||||
return s
|
||||
case map[int]uint8:
|
||||
for i := 0; i < len(t); i++ {
|
||||
s = append(s, float64(t[i]))
|
||||
}
|
||||
return s
|
||||
case map[int]uint16:
|
||||
for i := 0; i < len(t); i++ {
|
||||
s = append(s, float64(t[i]))
|
||||
}
|
||||
return s
|
||||
case map[int]uint32:
|
||||
for i := 0; i < len(t); i++ {
|
||||
s = append(s, float64(t[i]))
|
||||
}
|
||||
return s
|
||||
case map[int]uint64:
|
||||
for i := 0; i < len(t); i++ {
|
||||
s = append(s, float64(t[i]))
|
||||
}
|
||||
return s
|
||||
case map[int]bool:
|
||||
for i := 0; i < len(t); i++ {
|
||||
if t[i] {
|
||||
s = append(s, 1.0)
|
||||
} else {
|
||||
s = append(s, 0.0)
|
||||
}
|
||||
}
|
||||
return s
|
||||
case map[int]float64:
|
||||
for i := 0; i < len(t); i++ {
|
||||
s = append(s, t[i])
|
||||
}
|
||||
return s
|
||||
case map[int]time.Duration:
|
||||
for i := 0; i < len(t); i++ {
|
||||
r = append(r, t[i])
|
||||
}
|
||||
}
|
||||
for _, v := range r {
|
||||
switch t := v.(type) {
|
||||
case int:
|
||||
a := float64(t)
|
||||
f = append(f, a)
|
||||
case uint:
|
||||
f = append(f, float64(t))
|
||||
case float64:
|
||||
f = append(f, t)
|
||||
case string:
|
||||
fl, err := strconv.ParseFloat(t, 64)
|
||||
if err == nil {
|
||||
f = append(f, fl)
|
||||
}
|
||||
case bool:
|
||||
if t {
|
||||
f = append(f, 1.0)
|
||||
} else {
|
||||
f = append(f, 0.0)
|
||||
}
|
||||
case time.Duration:
|
||||
f = append(f, float64(t))
|
||||
}
|
||||
}
|
||||
return f
|
||||
}
|
||||
Executable
+31
@@ -0,0 +1,31 @@
|
||||
package maths
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"sort"
|
||||
)
|
||||
|
||||
func copyslice(input Float64Data) Float64Data {
|
||||
s := make(Float64Data, input.Len())
|
||||
copy(s, input)
|
||||
return s
|
||||
}
|
||||
|
||||
func sortedCopyDif(input Float64Data) (copy Float64Data) {
|
||||
if sort.Float64sAreSorted(input) {
|
||||
return input
|
||||
}
|
||||
copy = copyslice(input)
|
||||
sort.Float64s(copy)
|
||||
return
|
||||
}
|
||||
|
||||
func RandDigits(n uint) string {
|
||||
s := ""
|
||||
for n != 0 {
|
||||
s += fmt.Sprintf("%d", rand.Intn(10))
|
||||
n--
|
||||
}
|
||||
return s
|
||||
}
|
||||
Executable
+16
@@ -0,0 +1,16 @@
|
||||
package maths
|
||||
|
||||
import "math"
|
||||
|
||||
func Max(input Float64Data) (max float64, err error) {
|
||||
if input.Len() == 0 {
|
||||
return math.NaN(), EmptyInputErr
|
||||
}
|
||||
max = input.Get(0)
|
||||
for i := 1; i < input.Len(); i++ {
|
||||
if input.Get(i) > max {
|
||||
max = input.Get(i)
|
||||
}
|
||||
}
|
||||
return max, nil
|
||||
}
|
||||
Executable
+11
@@ -0,0 +1,11 @@
|
||||
package maths
|
||||
|
||||
import "math"
|
||||
|
||||
func Mean(input Float64Data) (float64, error) {
|
||||
if input.Len() == 0 {
|
||||
return math.NaN(), EmptyInputErr
|
||||
}
|
||||
sum, _ := input.Sum()
|
||||
return sum / float64(input.Len()), nil
|
||||
}
|
||||
Executable
+17
@@ -0,0 +1,17 @@
|
||||
package maths
|
||||
|
||||
import "math"
|
||||
|
||||
func Min(input Float64Data) (min float64, err error) {
|
||||
l := input.Len()
|
||||
if l == 0 {
|
||||
return math.NaN(), EmptyInputErr
|
||||
}
|
||||
min = input.Get(0)
|
||||
for i := 1; i < l; i++ {
|
||||
if input.Get(i) < min {
|
||||
min = input.Get(i)
|
||||
}
|
||||
}
|
||||
return min, nil
|
||||
}
|
||||
Executable
+41
@@ -0,0 +1,41 @@
|
||||
package maths
|
||||
|
||||
func Mode(input Float64Data) (mode []float64, err error) {
|
||||
l := input.Len()
|
||||
if l == 1 {
|
||||
return input, nil
|
||||
}
|
||||
if l == 0 {
|
||||
return nil, EmptyInputErr
|
||||
}
|
||||
c := sortedCopyDif(input)
|
||||
// Traverse sorted array,
|
||||
// tracking the longest repeating sequence
|
||||
mode = make([]float64, 5)
|
||||
cnt, maxCnt := 1, 1
|
||||
for i := 1; i < l; i++ {
|
||||
switch {
|
||||
case c[i] == c[i-1]:
|
||||
cnt++
|
||||
case cnt == maxCnt && maxCnt != 1:
|
||||
mode = append(mode, c[i-1])
|
||||
cnt = 1
|
||||
case cnt > maxCnt:
|
||||
mode = append(mode[:0], c[i-1])
|
||||
maxCnt, cnt = cnt, 1
|
||||
default:
|
||||
cnt = 1
|
||||
}
|
||||
}
|
||||
switch {
|
||||
case cnt == maxCnt:
|
||||
mode = append(mode, c[l-1])
|
||||
case cnt > maxCnt:
|
||||
mode = append(mode[:0], c[l-1])
|
||||
maxCnt = cnt
|
||||
}
|
||||
if maxCnt == 1 || len(mode)*maxCnt == l && maxCnt != l {
|
||||
return Float64Data{}, nil
|
||||
}
|
||||
return mode, nil
|
||||
}
|
||||
Executable
+23
@@ -0,0 +1,23 @@
|
||||
package maths
|
||||
|
||||
import "math"
|
||||
|
||||
func Round(input float64, places int) (rounded float64, err error) {
|
||||
if math.IsNaN(input) {
|
||||
return math.NaN(), NaNErr
|
||||
}
|
||||
sign := 1.0
|
||||
if input < 0 {
|
||||
sign = -1
|
||||
input *= -1
|
||||
}
|
||||
precision := math.Pow(10, float64(places))
|
||||
digit := input * precision
|
||||
_, decimal := math.Modf(digit)
|
||||
if decimal >= 0.5 {
|
||||
rounded = math.Ceil(digit)
|
||||
} else {
|
||||
rounded = math.Floor(digit)
|
||||
}
|
||||
return rounded / precision * sign, nil
|
||||
}
|
||||
Executable
+25
@@ -0,0 +1,25 @@
|
||||
package maths
|
||||
|
||||
import "math"
|
||||
|
||||
func Sum(input Float64Data) (sum float64, err error) {
|
||||
if input.Len() == 0 {
|
||||
return math.NaN(), EmptyInputErr
|
||||
}
|
||||
for _, n := range input {
|
||||
sum += n
|
||||
}
|
||||
return sum, nil
|
||||
}
|
||||
|
||||
func CumulativeInt64(a *int64, bs ...int64) *int64 {
|
||||
var c int64
|
||||
for _, b := range bs {
|
||||
c += b
|
||||
}
|
||||
if a == nil {
|
||||
return &c
|
||||
}
|
||||
*a += c
|
||||
return a
|
||||
}
|
||||
Executable
+49
@@ -0,0 +1,49 @@
|
||||
package maths
|
||||
|
||||
import "math"
|
||||
|
||||
// _variance finds the variance for both population and sample data
|
||||
func _variance(input Float64Data, sample int) (variance float64, err error) {
|
||||
if input.Len() == 0 {
|
||||
return math.NaN(), EmptyInputErr
|
||||
}
|
||||
// Sum the square of the mean subtracted from each number
|
||||
m, _ := Mean(input)
|
||||
for _, n := range input {
|
||||
variance += (n - m) * (n - m)
|
||||
}
|
||||
// When getting the mean of the squared differences
|
||||
// "sample" will allow us to know if it's a sample
|
||||
// or population and wether to subtract by one or not
|
||||
return variance / float64((input.Len() - (1 * sample))), nil
|
||||
}
|
||||
|
||||
// PopulationVariance finds the amount of variance within a population
|
||||
func PopulationVariance(input Float64Data) (pvar float64, err error) {
|
||||
v, err := _variance(input, 0)
|
||||
if err != nil {
|
||||
return math.NaN(), err
|
||||
}
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// CovariancePopulation computes covariance for entire population between two variables.
|
||||
func CovariancePopulation(data1, data2 Float64Data) (float64, error) {
|
||||
l1 := data1.Len()
|
||||
l2 := data2.Len()
|
||||
if l1 == 0 || l2 == 0 {
|
||||
return math.NaN(), EmptyInputErr
|
||||
}
|
||||
if l1 != l2 {
|
||||
return math.NaN(), SizeErr
|
||||
}
|
||||
m1, _ := Mean(data1)
|
||||
m2, _ := Mean(data2)
|
||||
var s float64
|
||||
for i := 0; i < l1; i++ {
|
||||
delta1 := (data1.Get(i) - m1)
|
||||
delta2 := (data2.Get(i) - m2)
|
||||
s += delta1 * delta2
|
||||
}
|
||||
return s / float64(l1), nil
|
||||
}
|
||||
Reference in New Issue
Block a user