Errors are handled by my List program, which should be compiled first (or comment out error messages).
Code:
LOCAL CRID:="Means V0.1 © 2018 StephenG1CMZ";
LOCAL MN:="Means.";
LOCAL MORETEXT:="A bag of mostly means.";//ST:TNG
//IMPORT({LIST}); //LIST Handles Error Messages
LOCAL EMPTY0:=0;//ADDITIVE
LOCAL EMPTY1:=1;//MULTIPLICATIVE
//NAN CAN BE GENERATED
//NONE OF THESE ROUTINES HANDLE NAN IN INPUT LST DATA
//BUT YOU CAN USE List.IsNumeric to check IF A LIST IS OK
//ERR
LOCAL NaN:="NaN";
LOCAL ListErrK:=1;//1=SHOW ERROR
//MLSTRING TO MATCH ML
LOCAL MLS:={
"MIN: ",
"MIN|: ",
"HarmonicMean: ",
"GeometricMean: ",
"GeometricMeanS: ",
"GeometricAverage: ",
"ArithmeticMean: ",
"InterQuartileMean: ",
"MidRange: ",
"RootMeanSquare RMS: ",
"Cubic: ",
"ContraHarmonicMean: ",
"PowerMean(−1): ",
"PowerMean(3): ",
"MAX: ",
"MAX|: " };
EXPORT ABOUT()
BEGIN
MSGBOX(CRID);
MSGBOX(MORETEXT);
END;
// List math procedures
// Probably only work on numeric lists
TBD()
BEGIN
MSGBOX("TBD");
END;
NAN()
BEGIN
RETURN NaN;
END;
EMPTIES(ST)
BEGIN
RAISE(MN+ST,EL,ListIsEmptyError,"",ListErrK);
RAISE(MN+ST,EL,ListStatisticsError,"",ListErrK);
RETURN NAN();
END;
DIVBY0(ST)
BEGIN
RAISE(MN+ST,EL,DivBy0Error,"",ListErrK);
RAISE(MN+ST,EL,ListStatisticsError,"",ListErrK);
RETURN NAN();//IN LIEU OF +INF OR −INF
END;
EXPORT ListΣLIST(LST)
BEGIN
RETURN IFTE(SIZE(LST),ΣLIST(LST),EMPTY0);
END;
EXPORT ListΠLIST(LST)
BEGIN
LOCAL SZ:=SIZE(LST);
IF SZ>1 THEN RETURN ΠLIST(LST);
END;
IF SZ==1 THEN RETURN LST(1);
END;
//IF SZ==0 THEN
RETURN EMPTY1;
//END;
END;
EXPORT ListCUMSUM(LST)
//Puzzle #41
//{}={0}
BEGIN
RETURN IFTE(SIZE(LST),cumSum(LST),{0});
END;
EXPORT ListMAX(LST)
BEGIN
RETURN IFTE(SIZE(LST),MAX(LST),EMPTY0);
END;
EXPORT ListMAXABS(LST)
//MAX MAGNITUDE IGNORING SIGN
//
BEGIN
RETURN MAX(ListMAX(LST),−ListMIN(LST));
END;
EXPORT ListMEAN(LST)
BEGIN
IF SIZE(LST) THEN
RETURN (mean(LST));
END;
RETURN EMPTIES("");
END;
//NB MEAN AND MEAN2 CURRENTLY RETURN TYPE RAT
//USE approx if you prefer real
EXPORT ListMEAN2(LSTV,LSTF)
BEGIN
IF SIZE(LSTV) AND SIZE(LSTF) THEN
RETURN (mean(LSTV,LSTF));
END;
RETURN EMPTIES("");
END;
//MEDIAN
EXPORT ListMIN(LST)
BEGIN
RETURN IFTE(SIZE(LST),MIN(LST),EMPTY0);
END;
EXPORT ListMINABS(LST)
BEGIN
IF SIZE(LST) THEN
RETURN MIN(ABS(LST));
END;
RETURN 0;
END;
//MODE
EXPORT ArithmeticMean(LST)
BEGIN
RETURN ListMEAN(LST);
END;
EXPORT ContraHarmonicMean(LST)
//POSITIVE LST
BEGIN
LOCAL DEN:=ListΣLIST(LST);
IF SIZE(LST) THEN
IF DEN THEN
RETURN ListΣLIST(LST^2)/DEN;
ELSE
RETURN DIVBY0("");
END;
END;
RETURN EMPTIES("");
END;
EXPORT CubicMean (LST)
BEGIN
LOCAL NN:=SIZE(LST);
IF NN THEN
RETURN approx(surd(((ListΣLIST(LST^3))/NN),3));
END;
RETURN EMPTIES("");
END;
GeometricAverage(LST)
//AVERAGE GROWTH FROM LST(1) TO LST(0) IN NN STEPS.
//NB INTERMEDIATE VALUES ARE NOT REFERENCED
//BUT SIZE OF LST IS
BEGIN
LOCAL AZ,AN;
LOCAL NNN:=SIZE(LST)-1;//BECAUSE 1.N NOT 0.N
IF NNN>0 THEN
AZ:=LST(1);
IF AZ THEN
AN:=LST(SIZE(LST));
RETURN (AN/AZ)^(1/NNN);
ELSE
RETURN DIVBY0("");
END;
END;
RETURN EMPTIES("");
END;
EXPORT GeometricMean(LST)
//Geometric mean
//Positive (not checked)
//ANY 0:0
//Products can overflow:See GMeanS
BEGIN
LOCAL NN:=SIZE(LST);
IF NN THEN
//using surd instead of ^1/N avoids <0FAIL
//negatives may yield imaginary mean
RETURN approx(surd(ListΠLIST(LST),NN));
END;
RETURN EMPTIES("");
END;
//NB WHEN NEGATIVES ARE PRESENT
//GMEAN AND GMEANS YIELD DIFFERING RESULTS
//VERIFY?
EXPORT GeometricMeanS(LST)
//SLOW VERSION USES LOGS TO AVOID OVERFLOW
//SO ABS TO AVOID NEGATIVES
//ANY 0=0 AS GMEAN
BEGIN
LOCAL MULT,SIGNLST;
LOCAL NN:=SIZE(LST);
IF NN THEN
IF POS(LST,0) THEN
RETURN 0;
END;
//MULTIPLY NEGATIVES TBC
//RECOMMENDED: MULT=(−1)^(MM/NN): MM=COUNT NEGATIVES
//TO AVOID COUNTING MM I THINK MULTIPLYING ALL SIGNS MAY BE QUICKER
//TBC
SIGNLST:=SIGN(LST);
MULT:=IFTE(POS(SIGNLST,−1),ListΠLIST(SIGNLST),1);//COULD JUST MULTIPLY ALWAYS
//EITHER LOG COULD BE USED
RETURN MULT*e^(ListΣLIST(LN(ABS(LST)))/NN);
END;
RETURN EMPTIES("");
END;
EXPORT HarmonicMean(LST)
//Positive preferred
//EG(1,−1)=/0=NAN
BEGIN
LOCAL NN:=SIZE(LST);
LOCAL DEN;
IF NN THEN
IF POS(LST,0) THEN
RETURN 0;//ANY 0=0
END;
DEN:=ΣLIST(1/LST);//0 UNEXPECTED:UNDERFLOW?=INF MEAN
RETURN IFTE(DEN,SIZE(LST)/DEN,NAN());//GUARD 0 DEN
END;
RETURN EMPTIES("");
END;
EXPORT InterQuartileMean (SORTEDLST)
//InterQuartileMean:List must be sorted
//TBC
//DO THE SLICE INDICES NEED CASTING TO INT
//IF SO ROUND OR TRUNC?
//THIS IMPLEMENT IS ONLY CORRECT IF THE SIZE IS DIVISBLE BY 4
//TBC
BEGIN
LOCAL NN:=SIZE(SORTEDLST);
IF SIZE(SORTEDLST)≥4 THEN
RETURN (2/NN)*ListΣLIST(SORTEDLST({(NN/4)+1,(3*NN/4)}));
END;
//SMALL LIST: FALLBACK TO MEAN
RETURN ArithmeticMean(SORTEDLST);//In this case it neednt be
END;
EXPORT InterQuartileMeanL(LST)
//This temporary version also works if not divisible by 4
//But is inefficient
//It is not recommended
BEGIN
LOCAL NN:=SIZE(LST);
//MAKE LST 4 TIMES BIGGER INSTEAD:MAY FAIL
LOCAL TMP;
TMP:=CONCAT(LST,LST);
TMP:=CONCAT(TMP,LST);
TMP:=CONCAT(TMP,LST);
TMP:=SORT(TMP);
RETURN (ArithmeticMean(TMP({NN+1,3*NN})));
END;
EXPORT MidRange(LST)
BEGIN
//MSGBOX("MID");
RETURN (ListMAX(LST)+ListMIN(LST))/2;
END;
EXPORT PowerMean (LST,PWR)
//AKA GeneralisedMean
//PWR:REAL NONZERO
//LST:POSITIVE SO ABS
//IMPLEMENT MAY DIFFER FROM CUBIC ETC
BEGIN
LOCAL NN:=SIZE(LST);
IF NN THEN
RETURN IFTE(PWR,approx(surd(((ListΣLIST(ABS(LST)^(PWR)))/NN),PWR)),DIVBY0(""));
END;
RETURN EMPTIES("");
END;
EXPORT RMS(LST)
BEGIN
LOCAL NN:=SIZE(LST);
IF NN THEN
RETURN √((ListΣLIST(LST^2))/NN);
END;
RETURN EMPTIES("");
END;
EXPORT RootMeanSqare(LST)
BEGIN
RETURN RMS(LST);
END;
EXPORT TruncatedMean(LST)
//EXCLUDE EXTREMES
BEGIN
TBD();
END;
//SPECIFY A PERCENTAGE OR SIMILAR TO EXCLUDE
EXPORT WinsorisedMean(LST)
//A VARIATION OF TRUNCATED:CLAMP EXTREMES
//There is an implementation in the library
BEGIN
TBD();
END;
EXPORT ManyMeans(LST)
//WHAT NUMBER DID YOU WANT? :)
BEGIN
LOCAL SAVED:=ListShowErrors;
LOCAL ML:={};
//SEQUENCE TO MATCH MLS
ListShowErrors:=0;
ML:={
ListMIN(LST),
ListMINABS(LST),
HarmonicMean(LST),
GeometricMean(LST),
GeometricMeanS(LST),
GeometricAverage(LST),
ArithmeticMean(LST),
InterQuartileMean(SORT(LST)),
MidRange(LST),
RMS(LST),
CubicMean(LST),
ContraHarmonicMean(LST),
PowerMean(LST,−1),
PowerMean(LST,3),
ListMAX(LST),
ListMAXABS(LST) };
ListShowErrors:=SAVED;
RETURN ML;
END;
EXPORT ManyMeansCHS(LST)
BEGIN
LOCAL II,TM,CHS;
LOCAL ML:={};
LOCAL RLST;
//PRINT(MN+" SIZE: "+SIZE(LST));//SIZE WARNS OF POSSIBLE SLOW CALCS
TM:=TEVAL(ML:=ManyMeans(LST));//TIMED CALCULATION
RLST:=MAKELIST((MLS(II)+ML(II)),II,1,SIZE(MLS));
CHOOSE(CHS,CRID,RLST);
//PRINT("Used "+TM);//Performance.And confirms list completed.
END;
EXPORT ManyMeansPRINT(LST)
BEGIN
LOCAL II,TM;
LOCAL ML:={};
PRINT();
PRINT(CRID);
PRINT(MN+" SIZE: "+SIZE(LST));//SIZE WARNS OF POSSIBLE SLOW CALCS
TM:=TEVAL(ML:=ManyMeans(LST));//TIMED CALCULATION
FOR II FROM 1 TO SIZE(MLS) DO
PRINT(MLS(II)+ML(II));
END;
PRINT("Used "+TM);//Performance.And confirms list completed.
END;
EXPORT IsMEAN(LST,XX,PWR)
//Is XX a possible mean
//First exact match
BEGIN
LOCAL ML:=ManyMeans(LST);
RETURN POS(ML,XX);
END;
EXPORT IsNAN(LST)
BEGIN
MSGBOX(MN+"IsNAN\nUse StephenG1CMZ's List.IsNUMERIC");
RETURN 0;
END;
EXPORT MeansSeeAlso ()
BEGIN
LOCAL KK;
LOCAL CatFuns:={
"cumSum",
"deltalist",
"max",
"mean",
"min",
"product",
"trunc"};
//Just Listed as a reminder:not Selectable
CHOOSE(KK,MN+" Relevant Cat Functions",CatFuns)
END;
EXPORT MEANS()
BEGIN
//DIVBY0("");//TEST
END;