package com.mindprod.example;
import static java.lang.System.*;
/**
* Demonstrate various ways of summarising/averaging a list of doubles with a single number.
*
* @author Roedy Green, Canadian Mind Products
* @version 1.0 2009-09-02
* @since 2009-09-02
*/
public final class TestSummary
{
/**
* test numbers to average
*/
private static final double[] TEST_DATA = { 223.0, 223.8, 221.8, 227.3, 223.6, 224.4, 222.6, 227.9, 227.2 };
/**
* test weights, need not be normalised. Must be one for each element in TEST_DATA.
*/
private static final double[] TEST_WEIGHTS = { .10, .5, .20, .5, .5, .5, .5, .3, .4 };
/**
* Compute ordinary arithmetic average
*
* @param numbers array of doubles
*
* @return the ordinary arithmetic average or NaN for an empty array.
* @throws NullPointerException if numbers is null
*/
@SuppressWarnings( { "WeakerAccess" } )
public static double arithmeticMean( double... numbers )
{
if ( numbers.length == 0 )
{
return Double.NaN;
}
double sum = 0;
for ( double number : numbers )
{
sum += number;
}
return sum / numbers.length;
}
/**
* Compute geometric mean, nth root of the product of all the numbers.
*
* @param numbers array of doubles
*
* @return the geometric mean or NaN for an empty array.
* @throws NullPointerException if numbers is null
* @see <a href="http://en.wikipedia.org/wiki/Geometric_mean">Wikipedia on geometric mean</a>
*/
@SuppressWarnings( { "WeakerAccess" } )
public static double geometricMean( double... numbers )
{
if ( numbers.length == 0 )
{
return Double.NaN;
}
double sum = 0;
for ( double number : numbers )
{
sum += Math.log( number );
}
return Math.exp( sum / numbers.length );
}
/**
* Compute harmonic mean, the reciprocal of the arithmetic mean of the reciprocals.
*
* @param numbers array of doubles
*
* @return the harmonic mean or NaN for an empty array.
* @throws NullPointerException if numbers is null
* @see <a href="http://en.wikipedia.org/wiki/Harmonic_mean">Wikipedia on harmonic mean</a>
*/
@SuppressWarnings( { "WeakerAccess" } )
public static double harmonicMean( double... numbers )
{
if ( numbers.length == 0 )
{
return Double.NaN;
}
double sum = 0;
for ( double number : numbers )
{
sum += 1 / number;
}
return 1 / ( sum / numbers.length );
}
/**
* main program to test/demonstrate average/summarising methods.
*
* @param args command line not used.
*/
public static void main( String[] args )
{
out.println( minimum( TEST_DATA ) );
out.println( powerMean( -50, TEST_DATA ) );
out.println( harmonicMean( TEST_DATA ) );
out.println( powerMean( -1, TEST_DATA ) );
out.println( powerMean( -.5, TEST_DATA ) );
out.println( geometricMean( TEST_DATA ) );
out.println( powerMean( .5, TEST_DATA ) );
out.println( powerMean( .9, TEST_DATA ) );
out.println( arithmeticMean( TEST_DATA ) );
out.println( powerMean( 1, TEST_DATA ) );
out.println( rmsMean( TEST_DATA ) );
out.println( powerMean( 2, TEST_DATA ) );
out.println( weightedMean( TEST_DATA, TEST_WEIGHTS ) );
out.println( powerMean( 50, TEST_DATA ) );
out.println( maximum( TEST_DATA ) );
out.println( arithmeticMean( Double.MAX_VALUE, Double.MAX_VALUE / 2 ) );
}
/**
* Find the biggest number
*
* @param numbers array of doubles
*
* @return the maximum value or NaN for an empty array.
* @throws NullPointerException if numbers is null
*/
@SuppressWarnings( { "WeakerAccess" } )
public static double maximum( double... numbers )
{
if ( numbers.length == 0 )
{
return Double.NaN;
}
double max = numbers[ 0 ];
for ( double number : numbers )
{
if ( number > max )
{
max = number;
}
}
return max;
}
/**
* Find the smallest number
*
* @param numbers array of doubles
*
* @return the minimum value or NaN for an empty array.
* @throws NullPointerException if numbers is null
*/
@SuppressWarnings( { "WeakerAccess" } )
public static double minimum( double... numbers )
{
if ( numbers.length == 0 )
{
return Double.NaN;
}
double min = numbers[ 0 ];
for ( int i = 1; i < numbers.length; i++ )
{
if ( numbers[ i ] < min )
{
min = numbers[ i ];
}
}
return min;
}
/**
* Compute power average, a generalisation of rms average. Aka Hölder or generalised mean.
*
* @param power, need not be integral. Must not be 0. power=2 is same as rms average.
* @param numbers array of doubles
*
* @return the generalised power mean or NaN for an empty array.
* @throws NullPointerException if numbers is null
* @see <a href="http://en.wikipedia.org/wiki/Generalized_mean>Wikipedia on generalised mean</a>
*/
@SuppressWarnings( { "WeakerAccess" } )
public static double powerMean( double power, double... numbers )
{
if ( numbers.length == 0 )
{
return Double.NaN;
}
double sum = 0;
for ( double number : numbers )
{
sum += Math.pow( number, power );
}
return Math.pow( sum / numbers.length, 1 / power );
}
/**
* Compute rms, (root mean square) average, aka quadratic average
*
* @param numbers array of doubles
*
* @return the rms average or NaN for an empty array.
* @throws NullPointerException if numbers is null
* @see <a href="http://en.wikipedia.org/wiki/Root_mean_square">Wikipedia on rms mean</a>
*/
@SuppressWarnings( { "WeakerAccess" } )
public static double rmsMean( double... numbers )
{
if ( numbers.length == 0 )
{
return Double.NaN;
}
double sum = 0;
for ( double number : numbers )
{
sum += number * number;
}
return Math.sqrt( sum / numbers.length );
}
/**
* Compute ordinary arithmetic average, with weights on each value.
* If all weights are equal e.g. 1, this is the same as an arithmetic mean.
*
* @param numbers array of doubles
* @param weights array of weights. Need non be normalised (i.e. add up to 1 or 100).
*
* @return the weighted arithmetic average or NaN for an empty array.
* @throws NullPointerException if numbers or weights is null
*/
@SuppressWarnings( { "WeakerAccess" } )
public static double weightedMean( double[] numbers, double[] weights )
{
assert numbers.length == weights.length : "Must have one weight per number";
if ( numbers.length == 0 )
{
return Double.NaN;
}
double sum = 0;
double weightSum = 0;
for ( int i = 0; i < numbers.length; i++ )
{
sum += numbers[ i ] * weights[ i ];
weightSum += weights[ i ];
}
return sum / weightSum;
}
}