2024-02-17 18:13:24 +00:00
|
|
|
|
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
|
|
|
|
|
|
2024-02-21 09:12:59 +00:00
|
|
|
|
// ToBase convertit n selon la base donnée.
|
2024-02-17 18:13:24 +00:00
|
|
|
|
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
|
|
|
|
|
}
|
|
|
|
|
|
2024-02-21 09:12:59 +00:00
|
|
|
|
// ToInteger convertit n en entier.
|
|
|
|
|
func ToInteger[N integer](n Number, base ...N) Number { return toType(n, Integer, base...) }
|
2024-02-17 18:13:24 +00:00
|
|
|
|
|
2024-02-21 09:12:59 +00:00
|
|
|
|
// ToDecimal convertit n en décimal.
|
|
|
|
|
func ToDecimal[N integer](n Number, base ...N) Number { return toType(n, Decimal, base...) }
|
2024-02-17 18:13:24 +00:00
|
|
|
|
|
2024-02-21 09:12:59 +00:00
|
|
|
|
// ToFraction convertit n en fraction.
|
|
|
|
|
func ToFraction[N integer](n Number, base ...N) Number { return toType(n, Fraction, base...) }
|
2024-02-17 18:13:24 +00:00
|
|
|
|
|
2024-02-21 09:12:59 +00:00
|
|
|
|
// ToScientific convertit n en nombre scientifique.
|
|
|
|
|
func ToScientific[N integer](n Number, base ...N) Number { return toType(n, Scientific, base...) }
|
2024-02-17 18:13:24 +00:00
|
|
|
|
|
|
|
|
|
// Fonctions de type f(n) → n
|
2024-02-21 09:12:59 +00:00
|
|
|
|
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() }
|
2024-02-17 18:13:24 +00:00
|
|
|
|
|
|
|
|
|
// Fonctions de type f(n, n) → n
|
2024-02-21 09:12:59 +00:00
|
|
|
|
func Cmp(n1, n2 Number) Number { return IntOf(n1.Cmp(n2)) }
|
2024-02-17 18:13:24 +00:00
|
|
|
|
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) }
|
2024-02-21 09:12:59 +00:00
|
|
|
|
func Bit(n1, n2 Number) Number { return IntOf(n1.Bit(n2)) }
|
2024-02-17 18:13:24 +00:00
|
|
|
|
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
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-02-21 09:12:59 +00:00
|
|
|
|
// Max retourne le nombre le plus grand de la liste.
|
2024-02-17 18:13:24 +00:00
|
|
|
|
func Max(numbers ...Number) (n Number) {
|
|
|
|
|
return Reduce(func(n1, n2 Number) Number {
|
|
|
|
|
if n2.Gt(n1) {
|
|
|
|
|
return n2
|
|
|
|
|
}
|
|
|
|
|
return n1
|
|
|
|
|
})(numbers...)
|
|
|
|
|
}
|
|
|
|
|
|
2024-02-21 09:12:59 +00:00
|
|
|
|
// Min retourne le nombre le plus petit de la liste.
|
2024-02-17 18:13:24 +00:00
|
|
|
|
func Min(numbers ...Number) (n Number) {
|
|
|
|
|
return Reduce(func(n1, n2 Number) Number {
|
|
|
|
|
if n2.Lt(n1) {
|
|
|
|
|
return n2
|
|
|
|
|
}
|
|
|
|
|
return n1
|
|
|
|
|
})(numbers...)
|
|
|
|
|
}
|
|
|
|
|
|
2024-02-21 09:12:59 +00:00
|
|
|
|
// Sum retourne la somme des nombres.
|
|
|
|
|
func Sum(numbers ...Number) (n Number) { return Reduce(Add)(numbers...) }
|
2024-02-17 18:13:24 +00:00
|
|
|
|
|
2024-02-21 09:12:59 +00:00
|
|
|
|
// Mean retourne la moyenne des nombres.
|
2024-02-17 18:13:24 +00:00
|
|
|
|
func Mean(numbers ...Number) (n Number) {
|
|
|
|
|
l := len(numbers)
|
|
|
|
|
if l == 0 {
|
|
|
|
|
return Nan()
|
|
|
|
|
}
|
|
|
|
|
|
2024-02-21 09:12:59 +00:00
|
|
|
|
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...)
|
|
|
|
|
if l&1 == 0 {
|
|
|
|
|
i := l >> 1
|
|
|
|
|
return numbers[i].Add(numbers[i-1]).Div(Two())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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
|
2024-02-17 18:13:24 +00:00
|
|
|
|
}
|
|
|
|
|
|
2024-02-21 09:12:59 +00:00
|
|
|
|
// 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.
|
2024-02-17 18:13:24 +00:00
|
|
|
|
func Round(n Number, precision uint64, base ...uint) Number {
|
|
|
|
|
if !n.IsDefined() || n.Type() == Integer {
|
|
|
|
|
return n
|
|
|
|
|
}
|
|
|
|
|
|
2024-02-21 09:12:59 +00:00
|
|
|
|
b := n.Base()
|
|
|
|
|
if len(base) > 0 {
|
|
|
|
|
b = formatBase(base...)
|
2024-02-17 18:13:24 +00:00
|
|
|
|
}
|
2024-02-21 09:12:59 +00:00
|
|
|
|
|
|
|
|
|
p := pow(b, precision)
|
2024-02-17 18:13:24 +00:00
|
|
|
|
num, denom := n.Num().Mul(p), n.Denom()
|
|
|
|
|
|
2024-02-21 09:12:59 +00:00
|
|
|
|
return num.Quo(denom).Div(p).ToType(n.Type())
|
2024-02-17 18:13:24 +00:00
|
|
|
|
}
|
|
|
|
|
|
2024-02-21 09:12:59 +00:00
|
|
|
|
// Reverse inverse l’ordre de la liste des nombres.
|
2024-02-17 18:13:24 +00:00
|
|
|
|
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
|
|
|
|
|
}
|
|
|
|
|
|
2024-02-21 09:12:59 +00:00
|
|
|
|
// Sort trie les nombres par ordre croissant.
|
2024-02-17 18:13:24 +00:00
|
|
|
|
func Sort(numbers ...Number) []Number {
|
|
|
|
|
sort.Slice(numbers, func(i, j int) bool {
|
|
|
|
|
return numbers[i].Lt(numbers[j])
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
return numbers
|
|
|
|
|
}
|
|
|
|
|
|
2024-02-21 09:12:59 +00:00
|
|
|
|
// SortDesc trie les nombres par ordre décroissant.
|
2024-02-17 18:13:24 +00:00
|
|
|
|
func SortDesc(numbers ...Number) []Number {
|
|
|
|
|
sort.Slice(numbers, func(i, j int) bool {
|
|
|
|
|
return numbers[i].Gt(numbers[j])
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
return numbers
|
|
|
|
|
}
|