2021-01-29 06:31:58 -05:00
|
|
|
|
|
|
|
[![Arduino CI](https://github.com/RobTillaart/statHelpers/workflows/Arduino%20CI/badge.svg)](https://github.com/marketplace/actions/arduino_ci)
|
2021-12-28 09:37:03 -05:00
|
|
|
[![Arduino-lint](https://github.com/RobTillaart/statHelpers/actions/workflows/arduino-lint.yml/badge.svg)](https://github.com/RobTillaart/statHelpers/actions/workflows/arduino-lint.yml)
|
|
|
|
[![JSON check](https://github.com/RobTillaart/statHelpers/actions/workflows/jsoncheck.yml/badge.svg)](https://github.com/RobTillaart/statHelpers/actions/workflows/jsoncheck.yml)
|
2021-01-29 06:31:58 -05:00
|
|
|
[![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](https://github.com/RobTillaart/statHelpers/blob/master/LICENSE)
|
|
|
|
[![GitHub release](https://img.shields.io/github/release/RobTillaart/statHelpers.svg?maxAge=3600)](https://github.com/RobTillaart/statHelpers/releases)
|
|
|
|
|
2021-12-28 09:37:03 -05:00
|
|
|
|
2021-01-29 06:31:58 -05:00
|
|
|
# statHelpers
|
|
|
|
|
|
|
|
Arduino library with a number of statistic helper functions.
|
|
|
|
|
2021-12-28 09:37:03 -05:00
|
|
|
|
2021-01-29 06:31:58 -05:00
|
|
|
## Description
|
|
|
|
|
|
|
|
This library contains functions that have the goal to help with
|
|
|
|
some basic statistical calculations.
|
|
|
|
|
|
|
|
|
|
|
|
## Functions
|
|
|
|
|
|
|
|
### Permutation
|
|
|
|
|
2021-12-28 09:37:03 -05:00
|
|
|
Returns how many different ways one can choose a set of k elements from a set of n.
|
|
|
|
The order does matter so (1, 2) is not equal to (2, 1).
|
2021-01-29 06:31:58 -05:00
|
|
|
The limits mentioned is the n for which all k still work.
|
|
|
|
|
2021-12-28 09:37:03 -05:00
|
|
|
- **uint32_t permutations(n, k)** exact up to n = 12
|
|
|
|
- **uint64_t permutations64(n, k)** exact up to n = 20
|
|
|
|
- **double dpermutations(n, k)** not exact up to n = 34 (4 byte) or n = 170 (8 byte)
|
2021-01-29 06:31:58 -05:00
|
|
|
|
2021-12-28 09:37:03 -05:00
|
|
|
If you need a larger n but k is near 0 the functions will still work.
|
|
|
|
To which value of k the formulas work differs per value for n.
|
|
|
|
No formula found, and build in an overflow detection takes overhead, so that is not done.
|
2021-01-29 06:31:58 -05:00
|
|
|
|
|
|
|
|
|
|
|
- **nextPermutation<Type>(array, size)** given an array of type T it finds the next permutation
|
|
|
|
of that array in a lexicographical way. ABCD --> ABDC.
|
|
|
|
Based upon // http://www.nayuki.io/page/next-lexicographical-permutation-algorithm although
|
|
|
|
other same code examples exist.
|
|
|
|
|
|
|
|
|
|
|
|
### Factorial
|
|
|
|
|
2021-12-28 09:37:03 -05:00
|
|
|
- **uint32_t factorial(n)** exact up to n = 12.
|
|
|
|
- **uint64_t factorial64(n)** exact up to n = 20. (Print 64 bit ints with my printHelpers)
|
|
|
|
- **double dfactorial(n)** not exact up to n = 34 (4 byte) or n = 170 (8 byte).
|
|
|
|
- **double stirling(n)** approximation function for factorial (right magnitude).
|
2021-01-29 06:31:58 -05:00
|
|
|
|
|
|
|
**dfactorial()** is quite accurate over the whole range.
|
|
|
|
**stirling()** is up to 3x faster for large n (> 100),
|
|
|
|
but accuracy is less than the **dfactorial()**, see example.
|
|
|
|
|
|
|
|
|
2021-08-06 11:19:47 -04:00
|
|
|
### SemiFactorial
|
|
|
|
|
|
|
|
- **uint32_t semiFactorial(n)** exact up to 20!!
|
|
|
|
- **uint64_t semiFactorial64(n)** exact up to 33!! (Print 64 bit integers with my printHelpers)
|
|
|
|
- **double dSemiFactorial(n)** not exact up to 56!! (4 byte) or 300!! (8 byte)
|
|
|
|
|
|
|
|
SemiFactorial are defined for
|
|
|
|
- **odd** values: n x (n-2) x (n-4) ... x 1
|
|
|
|
- **even** values: n x (n-2) x (n-4) ... x 2
|
|
|
|
|
|
|
|
Notes:
|
|
|
|
```n! = n!! x (n-1)!!``` this formula allows to calculate the value of n! indirectly
|
|
|
|
|
|
|
|
|
|
|
|
### Combinations
|
2021-01-29 06:31:58 -05:00
|
|
|
|
2021-12-28 09:37:03 -05:00
|
|
|
Returns how many different ways one can choose a set of k elements from a set of n.
|
|
|
|
The order does **not** matter so (1, 2) is equal to (2, 1).
|
2021-01-29 06:31:58 -05:00
|
|
|
The number of combinations grows fast so n is limited per function.
|
|
|
|
The limits mentioned is the n for which all k still work.
|
|
|
|
|
2021-12-28 09:37:03 -05:00
|
|
|
- **uint32_t combinations(n, k)** n = 0 .. 30 (iterative version)
|
|
|
|
- **uint64_t combinations64(n, k)** n = 0 .. 61 (iterative version)
|
2021-01-29 06:31:58 -05:00
|
|
|
- **uint32_t rcombinations(n, k)** n = 0 .. 30 (recursive version, slightly slower)
|
|
|
|
- **uint64_t rcombinations64(n, k)** n = 0 .. 61 (recursive version, slightly slower)
|
2021-12-28 09:37:03 -05:00
|
|
|
- **double dcombinations(n, k)** n = 0 .. 125 (4bit) n = 0 .. 1020 (8 bit)
|
2021-01-29 06:31:58 -05:00
|
|
|
|
2021-12-28 09:37:03 -05:00
|
|
|
If you need a larger n but k is near 0 the functions will still work.
|
|
|
|
To which value of k the formulas work differs per value for n.
|
|
|
|
No formula found, and build in an overflow detection takes overhead, so that is not done.
|
2021-01-29 06:31:58 -05:00
|
|
|
|
|
|
|
|
|
|
|
- **combPascal(n, k)** n = 0 .. 30 but due to double recursion per iteration it takes
|
|
|
|
time and a lot of it for larger values. Added for recreational purposes, limited tested.
|
2021-12-28 09:37:03 -05:00
|
|
|
Uses Pascal's triangle.
|
2021-01-29 06:31:58 -05:00
|
|
|
|
|
|
|
|
|
|
|
## Notes
|
|
|
|
|
2021-12-28 09:37:03 -05:00
|
|
|
- **perm1** is a sketch in the examples that shows a recursive permutation algorithm.
|
|
|
|
It generates all permutations of a given char string.
|
2021-01-29 06:31:58 -05:00
|
|
|
It allows you to process every instance.
|
|
|
|
It is added to this library as it fits in the context.
|
|
|
|
|
|
|
|
|
2021-08-06 11:19:47 -04:00
|
|
|
### Experimental - large numbers
|
|
|
|
|
|
|
|
|
2021-12-28 09:37:03 -05:00
|
|
|
- **void bigFactorial(uint32_t n, double &mantissa, uint32_t &exponent)**
|
|
|
|
returns a double mantissa between 0 and 10, and an integer exponent.
|
|
|
|
- **void bigPermutation(uint32_t n, uint32_t k, double &mantissa, uint32_t &exponent)**
|
|
|
|
returns a double mantissa between 0 and 10, and an integer exponent.
|
|
|
|
- **void bigCombination(uint32_t n, uint32_t k, double &mantissa, uint32_t &exponent)**
|
|
|
|
returns a double mantissa between 0 and 10, and an integer exponent.
|
|
|
|
|
|
|
|
An experimental **bigFactorial(n)** calculation to get an idea of the big numbers.
|
|
|
|
it can calculate factorials up to an exponent of 4294967295 max. 100.000.000! can be
|
|
|
|
done in 38 minutes on an ESP32 at 240 MHz.
|
|
|
|
Maximum value for n is **518678059! == 2.1718890e4294967292** a number that took ~10 hrs to calculate.
|
2021-08-06 11:19:47 -04:00
|
|
|
|
2021-12-28 09:37:03 -05:00
|
|
|
An experimental **bigPermutation(n, k)** calculation, to handle big numbers too.
|
|
|
|
Maximum value for n is **518678059** to have full range support. For small(er)
|
|
|
|
values of k, n can even be much larger, but not larger than 4294967295 max.
|
2021-08-06 11:19:47 -04:00
|
|
|
|
2021-12-28 09:37:03 -05:00
|
|
|
An experimental **bigCombination(n, k)** calculation for big numbers.
|
|
|
|
Not investigated what its maximum value is, but it should be higher than **518678059** as the number
|
|
|
|
of combinations is always smaller than number of permutations.
|
2021-08-06 11:19:47 -04:00
|
|
|
|
|
|
|
|
|
|
|
#### Experimental - not investigated yet
|
|
|
|
|
2021-12-28 09:37:03 -05:00
|
|
|
To have support for huge numbers one could upgrade the code to use uint64_t as parameter and
|
|
|
|
internally but calculating these values could take a lot of time, although **bigPermutations64(n, k)**
|
|
|
|
and **bigCombinations64(n, k)** would work fast for small values of k.
|
2021-08-06 11:19:47 -04:00
|
|
|
|
2021-12-28 09:37:03 -05:00
|
|
|
- **void bigFactorial64(uint64_t n, double &mantissa, uint64_t &exponent)**
|
|
|
|
returns a double mantissa between 0 and 10, and an integer exponent.
|
|
|
|
- **void bigPermutation64(uint64_t n, uint64_t k, double &mantissa, uint64_t &exponent)**
|
|
|
|
returns a double mantissa between 0 and 10, and an integer exponent.
|
|
|
|
- **void bigCombination64(uint64_t n, uint64_t k, double &mantissa, uint64_t &exponent)**
|
|
|
|
returns a double mantissa between 0 and 10, and an integer exponent.
|
2021-08-06 11:19:47 -04:00
|
|
|
|
|
|
|
|
2021-12-28 09:37:03 -05:00
|
|
|
## Operation
|
|
|
|
|
|
|
|
See examples
|
|
|
|
|
2021-08-06 11:19:47 -04:00
|
|
|
|
2021-01-29 06:31:58 -05:00
|
|
|
## Future
|
|
|
|
|
|
|
|
- code & example for get Nth Permutation
|
|
|
|
- investigate valid range detection for a given (n, k) for combinations and permutations.
|
2021-08-06 11:19:47 -04:00
|
|
|
- investigate a bigFloat class to do math for permutations and combinations to substantially larger values.
|
2021-12-28 09:37:03 -05:00
|
|
|
- Look for optimizations
|
|
|
|
- Look for ways to extend the scope
|
2021-01-29 06:31:58 -05:00
|
|
|
|