FastStatistics.java

package ac.essex.ooechs.imaging.commons.fast; 
 
import ac.essex.ooechs.imaging.commons.StatisticsSolver; 
 
/** 
 * A much faster way to calculate the standard deviation. There 
 * is no need to store all the values of x. 
 * 
 * Formula taken from this excellent site: 
 * http://www.sciencebuddies.org/mentoring/project_data_analysis_variance_std_deviation.shtml 
 * 
 * @author Olly Oechsle, University of Essex, Date: 06-Mar-2008 
 * @version 1.0 
 */ 
public class FastStatistics { 
 
    private float sumXSquared = 0; 
    private float totalX = 0; 
    private int n = 0; 
    private float max = Float.MIN_VALUE; 
    private float min = Float.MAX_VALUE; 
 
    public static void main(String[] args) { 
 
        StatisticsSolver mean1 = new StatisticsSolver(); 
 
        for (int n = 0; n < 10; n++) { 
 
            long start = System.currentTimeMillis(); 
            for (int i = 0; i <100000; i++) { 
            StatisticsSolver s = new StatisticsSolver(); 
            s.addData(3); 
            s.addData(4); 
            s.addData(4); 
            s.addData(5); 
            s.addData(6); 
            s.addData(8); 
            s.getStandardDeviation(); 
            } 
 
            long time = System.currentTimeMillis() - start; 
            mean1.addData(time); 
 
            System.out.println(time + "ms"); 
 
        } 
 
        System.out.println("Original Mean Time: " + mean1.getMean()); 
 
        StatisticsSolver mean2 = new StatisticsSolver(); 
 
        for (int n = 0; n < 10; n++) { 
 
            long start = System.currentTimeMillis(); 
            for (int i = 0; i <100000; i++) { 
            FastStatistics s = new FastStatistics(); 
            s.addData(3); 
            s.addData(4); 
            s.addData(4); 
            s.addData(5); 
            s.addData(6); 
            s.addData(8); 
            s.getStandardDeviation(); 
            } 
            long time = System.currentTimeMillis() - start; 
            mean2.addData(time); 
 
            System.out.println(time + "ms"); 
 
        } 
 
        System.out.println("Efficient Mean Time: " + mean2.getMean()); 
 
    } 
 
    /** 
     * Allows you to get the statistic by a numeric type instead of calling the right method. 
     * Useful if you want to choose which method during runtime. 
     */ 
    public float getStatistic(int type) { 
        switch (type) { 
            case StatisticsSolver.TOTAL: 
                return getTotal(); 
            case StatisticsSolver.MEAN: 
                return getMean(); 
            case StatisticsSolver.MAX: 
                return getMax(); 
            case StatisticsSolver.MIN: 
                return getMin(); 
            case StatisticsSolver.RANGE: 
                return getRange(); 
            case StatisticsSolver.VARIANCE: 
                return getVariance(); 
            case StatisticsSolver.STANDARD_DEVIATION: 
                return getStandardDeviation(); 
        } 
        throw new RuntimeException("Invalid statistic type: " + type); 
    } 
 
    public void addData(float x) { 
        totalX += x; 
        sumXSquared += (x * x); 
        if (x > max) max = x; 
        if (x < min) min = x; 
        n++; 
    } 
 
    public float getTotal() { 
        return totalX; 
    } 
 
    public float getMean() { 
        return totalX / n; 
    } 
 
    public float getVariance() { 
        float mean = getMean(); 
        return (sumXSquared / n) - (mean * mean); 
    } 
 
    public float getStandardDeviation() { 
        return (float) Math.sqrt(getVariance()); 
    } 
 
    public float getRange() { 
        return max - min; 
    } 
 
    public float getMax() { 
        return max; 
    } 
 
    public float getMin() { 
        return min; 
    } 
 
    public void reset() { 
        sumXSquared = 0; 
        totalX = 0; 
        n = 0; 
    } 
 
}