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...) 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 } // 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 }