242 lines
6.0 KiB
Go
242 lines
6.0 KiB
Go
package number
|
||
|
||
import (
|
||
"sort"
|
||
)
|
||
|
||
type Op1Func func(Number) Number
|
||
type Op2Func func(Number, Number) Number
|
||
type Op1To2Func func(Number) (Number, Number)
|
||
type Op2To2Func func(Number, Number) (Number, Number)
|
||
type ReduceFunc func(...Number) Number
|
||
type MapFunc func(...Number) []Number
|
||
|
||
// ToBase convertit n selon la base donnée.
|
||
func ToBase[N integer](n Number, base N) Number {
|
||
return n.ToBase(formatBase(base))
|
||
}
|
||
|
||
func toType[N integer](n Number, t NumberType, base ...N) Number {
|
||
n = n.ToType(t)
|
||
if len(base) > 0 {
|
||
n = ToBase(n, base[0])
|
||
}
|
||
|
||
return n
|
||
}
|
||
|
||
// ToInteger convertit n en entier.
|
||
func ToInteger[N integer](n Number, base ...N) Number { return toType(n, Integer, base...) }
|
||
|
||
// ToDecimal convertit n en décimal.
|
||
func ToDecimal[N integer](n Number, base ...N) Number { return toType(n, Decimal, base...) }
|
||
|
||
// ToFraction convertit n en fraction.
|
||
func ToFraction[N integer](n Number, base ...N) Number { return toType(n, Fraction, base...) }
|
||
|
||
// ToScientific convertit n en nombre scientifique.
|
||
func ToScientific[N integer](n Number, base ...N) Number { return toType(n, Scientific, base...) }
|
||
|
||
// Fonctions de type f(n) → n
|
||
func Neg(n Number) Number { return n.Neg() }
|
||
func Abs(n Number) Number { return n.Abs() }
|
||
func Num(n Number) Number { return n.Num() }
|
||
func Denom(n Number) Number { return n.Denom() }
|
||
func Inc(n Number) Number { return n.Inc() }
|
||
func Dec(n Number) Number { return n.Dec() }
|
||
func Inv(n Number) Number { return n.Inv() }
|
||
func Fact(n Number) Number { return n.Fact() }
|
||
func Len(n Number) Number { return IntOf(n.Len()) }
|
||
func Sqrt(n Number) Number { return n.Sqrt() }
|
||
func Square(n Number) Number { return n.Square() }
|
||
|
||
// Fonctions de type f(n, n) → n
|
||
func Cmp(n1, n2 Number) Number { return IntOf(n1.Cmp(n2)) }
|
||
func Eq(n1, n2 Number) Number { return ParseBool(n1.Eq(n2)) }
|
||
func Ne(n1, n2 Number) Number { return ParseBool(n1.Ne(n2)) }
|
||
func Gt(n1, n2 Number) Number { return ParseBool(n1.Gt(n2)) }
|
||
func Lt(n1, n2 Number) Number { return ParseBool(n1.Lt(n2)) }
|
||
func Ge(n1, n2 Number) Number { return ParseBool(n1.Ge(n2)) }
|
||
func Le(n1, n2 Number) Number { return ParseBool(n1.Le(n2)) }
|
||
func Add(n1, n2 Number) Number { return n1.Add(n2) }
|
||
func Sub(n1, n2 Number) Number { return n1.Sub(n2) }
|
||
func Mul(n1, n2 Number) Number { return n1.Mul(n2) }
|
||
func Div(n1, n2 Number) Number { return n1.Div(n2) }
|
||
func Quo(n1, n2 Number) Number { return n1.Quo(n2) }
|
||
func Rem(n1, n2 Number) Number { return n1.Rem(n2) }
|
||
func Lsh(n1, n2 Number) Number { return n1.Lsh(n2) }
|
||
func Rsh(n1, n2 Number) Number { return n1.Rsh(n2) }
|
||
func Bit(n1, n2 Number) Number { return IntOf(n1.Bit(n2)) }
|
||
func Pow(n1, n2 Number) Number { return n1.Pow(n2) }
|
||
func Sqrtn(n1, n2 Number) Number { return n1.Sqrtn(n2) }
|
||
|
||
// Fonctions de type f(n) → (n, n)
|
||
func NumDenom(n Number) (Number, Number) { return n.NumDenom() }
|
||
|
||
// Fonctions de type f(n, n) → (n, n)
|
||
func QuoRem(n1, n2 Number) (Number, Number) { return n1.QuoRem(n2) }
|
||
|
||
// Autre
|
||
func Map(callback Op1Func) MapFunc {
|
||
return func(numbers ...Number) []Number {
|
||
out := make([]Number, len(numbers))
|
||
for i, n := range numbers {
|
||
out[i] = callback(n)
|
||
}
|
||
|
||
return out
|
||
}
|
||
}
|
||
|
||
func Reduce(callback Op2Func) ReduceFunc {
|
||
return func(numbers ...Number) Number {
|
||
var acc Number
|
||
for i, n := range numbers {
|
||
if i == 0 {
|
||
acc = n
|
||
} else {
|
||
acc = callback(acc, n)
|
||
}
|
||
}
|
||
|
||
return acc
|
||
}
|
||
}
|
||
|
||
// Max retourne le nombre le plus grand de la liste.
|
||
func Max(numbers ...Number) (n Number) {
|
||
return Reduce(func(n1, n2 Number) Number {
|
||
if n2.Gt(n1) {
|
||
return n2
|
||
}
|
||
return n1
|
||
})(numbers...)
|
||
}
|
||
|
||
// Min retourne le nombre le plus petit de la liste.
|
||
func Min(numbers ...Number) (n Number) {
|
||
return Reduce(func(n1, n2 Number) Number {
|
||
if n2.Lt(n1) {
|
||
return n2
|
||
}
|
||
return n1
|
||
})(numbers...)
|
||
}
|
||
|
||
// Sum retourne la somme des nombres.
|
||
func Sum(numbers ...Number) (n Number) { return Reduce(Add)(numbers...) }
|
||
|
||
// Mean retourne la moyenne des nombres.
|
||
func Mean(numbers ...Number) (n Number) {
|
||
l := len(numbers)
|
||
if l == 0 {
|
||
return Nan()
|
||
}
|
||
|
||
return Sum(numbers...).Div(IntOf(l))
|
||
}
|
||
|
||
// Median retourne la médiane des nombres.
|
||
func Median(numbers ...Number) Number {
|
||
l := len(numbers)
|
||
if l == 0 {
|
||
return Nan()
|
||
}
|
||
|
||
numbers = Sort(numbers...)
|
||
return numbers[l>>1]
|
||
}
|
||
|
||
// Mode retourne retourne le mode des nombres (ie. le nombre le plus fréquent).
|
||
func Mode(numbers ...Number) Number {
|
||
l := len(numbers)
|
||
if l == 0 {
|
||
return Nan()
|
||
}
|
||
|
||
m := make(map[Number]int)
|
||
loop:
|
||
for _, n := range numbers {
|
||
for k := range m {
|
||
if k.Eq(n) {
|
||
m[k]++
|
||
continue loop
|
||
}
|
||
}
|
||
m[n] = 1
|
||
}
|
||
|
||
i := 0
|
||
var n Number
|
||
for k, j := range m {
|
||
if j > i {
|
||
n, i = k, j
|
||
}
|
||
}
|
||
|
||
return n
|
||
}
|
||
|
||
// Variance retourne la variance des nombres.
|
||
func Variance(numbers ...Number) Number {
|
||
m := Mean(numbers...)
|
||
if m.IsNan() {
|
||
return m
|
||
}
|
||
|
||
numbers = Map(func(n Number) Number {
|
||
return n.Sub(m).Square()
|
||
})(numbers...)
|
||
|
||
return Mean(numbers...)
|
||
}
|
||
|
||
// StdDeviation retourne l’écart-type des nombres.
|
||
func StdDeviation(numbers ...Number) Number { return Variance(numbers...).Sqrt() }
|
||
|
||
// Round arrondit le n selon la précision et la base données.
|
||
func Round(n Number, precision uint64, base ...uint) Number {
|
||
if !n.IsDefined() || n.Type() == Integer {
|
||
return n
|
||
}
|
||
|
||
b := n.Base()
|
||
if len(base) > 0 {
|
||
b = formatBase(base...)
|
||
}
|
||
|
||
p := pow(b, precision)
|
||
num, denom := n.Num().Mul(p), n.Denom()
|
||
|
||
return num.Quo(denom).Div(p).ToType(n.Type())
|
||
}
|
||
|
||
// Reverse inverse l’ordre de la liste des nombres.
|
||
func Reverse(numbers ...Number) []Number {
|
||
l := len(numbers)
|
||
for i := 0; i < l>>1; i++ {
|
||
j := l - 1 - i
|
||
numbers[i], numbers[j] = numbers[j], numbers[i]
|
||
}
|
||
|
||
return numbers
|
||
}
|
||
|
||
// Sort trie les nombres par ordre croissant.
|
||
func Sort(numbers ...Number) []Number {
|
||
sort.Slice(numbers, func(i, j int) bool {
|
||
return numbers[i].Lt(numbers[j])
|
||
})
|
||
|
||
return numbers
|
||
}
|
||
|
||
// SortDesc trie les nombres par ordre décroissant.
|
||
func SortDesc(numbers ...Number) []Number {
|
||
sort.Slice(numbers, func(i, j int) bool {
|
||
return numbers[i].Gt(numbers[j])
|
||
})
|
||
|
||
return numbers
|
||
}
|