rerror
Description
rerror() is a random number generator (RNG) that generates random error from a population with and , and with user-defined amounts of skewness and (excess) kurtosis. It uses the Fleishman power method to achieve this.
Syntax
rerror([rows=1], [cols=1], [skew=0], [kurt=0], [seed_str]) where
rowsandcolsdefine the shape of the outputskewis the desired skewness, defaulting to zero. Negative values are possible.kurtis the desired kurtosis, defaulting to zero. This must be a positive number.seed_stris a memorable seed string. If omitted then a quasi-unique seed is used to generate a non-volatile output; see the documentation ofruniffor more detail about this. Use a memorable string of your choosing if you want to set an explicit seed for reproducibility purposes, and useGetSeedif you want a volatile output.
If rerror is called without specifying values for either skew or kurt then rerror will draw values from the standard normal distribution.
You can specify any value, positive or negative, for the skewness. The kurtosis must be positive (or zero) and its minimum possible value is given by
If you specify a skew but not a kurtosis, then a value near the minimum kurtosis will be used. If you specify both a skew and a kurtosis, but the kurtosis is too small, then an error message will be returned.
There are also some maximum values of skew and kurt for which no valid solution can be found, in which case an error message to that effect will be displayed. This is simply a limitation of the Fleishman power method; if you want a simulation with larger skew and kurtosis, try drawing samples from a lognormal distribution, which is famous for its long tail.
This function is well-suited for quick & dirty work but for simulation demos you will either want to set the seed with a memorable string or use the volatile version of this function, rerrorV. Also please read the caveats about choosing seed strings in the runif documentation; they apply to this function too.
Example
The example below (and the attached spreadsheet) shows how rerror can be used to generate random numbers with different skews and kurtosis, independent of the mean and standard deviation.

Download: rerror.xlsx
Source Code
Helpers used: FSolve, FSolveBump, FSolveLadder, FSolveMonotonic
rerror = LAMBDA(
[rows], [cols], // size of matrix returned (default of 1 for both)
[skew], [kurt], // desired skewness and excess kurtosis (default 0 for both)
[seed_str], // optional seed string (default uses this workbook's CLS_SystemSeed)
LET(
// default values
rows, IF(ISOMITTED(rows), 1, rows),
cols, IF(ISOMITTED(cols), 1, cols),
skew, IF(ISOMITTED(skew), 0, skew),
// do not allow kurtosis below minimum or below zero
kmin, MAX(0, Fkmin(skew)),
// error if the user explicitly asked for a kurtosis below the feasible minimum
kurtTooSmall, IF(ISOMITTED(kurt), FALSE, kurt < kmin),
kurt, IF(ISOMITTED(kurt), ROUNDUP(kmin,0), kurt),
// solve for coefficients, retrying across starting values and (if needed)
// slightly bumped kurtosis until a valid monotonic solution is found
coeffs, FSolveBump(skew, kurt),
// general random numbers
IF(
kurtTooSmall,
"ERROR: kurtosis too small for skew = " & skew & "; must be at least " & TEXT(kmin, "0.00"),
IF(
AND(skew = 0, kurt = 0),
// use rnorm
rnorm(rows, cols, 0, 1, seed_str),
IF(
INDEX(coeffs, 1, 6) = 0,
"ERROR: no valid distribution found for skew = " & skew & ", kurt = " & kurt,
// use Flieshman method
LET(
z, NORM.S.INV(runif(rows, cols, ,,,seed_str)),
b, INDEX(coeffs, 1, 1),
c, INDEX(coeffs, 1, 2),
d, INDEX(coeffs, 1, 3),
-c + b*z + c*z^2 + d*z^3
)
)
)
)
)
);