/* * xtc - The eXTensible Compiler * Copyright (C) 2004-2007 Robert Grimm * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ package xtc.util; import java.util.ArrayList; import java.util.Collections; import java.util.List; /** * Implementation of a simple statistics collector. * * @author Robert Grimm * @version $Revision: 1.13 $ */ public class Statistics { /** The list of numbers. */ private List<Double> numbers; /** Create a new statistics collector. */ public Statistics() { numbers = new ArrayList<Double>(); } /** Reset this statistics collector. */ public void reset() { numbers.clear(); } /** * Add the specified number. * * @param d The number. */ public void add(final double d) { numbers.add(d); } /** * Get the size of this collection. * * @return The size. */ public int size() { return numbers.size(); } /** * Get the specified number. * * @param idx The index. * @return The corresponding number. * @throws IndexOutOfBoundsException * Signals that the index is out of range. */ public double get(final int idx) { return numbers.get(idx); } /** * Calculate the sum. * * @return The sum. */ public double sum() { double sum = 0; final int size = numbers.size(); for (int i=0; i<size; i++) { sum += numbers.get(i); } return sum; } /** * Calculate the mean. * * @return The mean. */ public double mean() { double mean = 0; final int size = numbers.size(); for (int i=0; i<size; i++) { mean += (numbers.get(i) - mean) / (i + 1); } return mean; } /** * Calculate the median. Note that this method does not change the * order of numbers in this collection, i.e. it sorts a copy. * * @return The median. */ public double median() { if (0 == size()) { return 0; } else { List<Double> sorted = new ArrayList<Double>(numbers); Collections.sort(sorted); return sorted.get(size()/2); } } /** * Calculate the standard deviation. * * @return The standard deviation. */ public double stdev() { final double mean = mean(); double variance = 0; final int size = size(); for (int i=0; i<size; i++) { final double diff = numbers.get(i) - mean; variance += (diff * diff - variance) / (i + 1); } return Math.sqrt(variance); } /** * Round the specified number to two digits after the decimal point. * * @param d The number. * @return The rounded number. */ public static double round(final double d) { return (Math.floor((d * 100) + 0.5)/100); } /** * Compute the least squares fit. This method computes the least * squares fit to a straight line model without a constant term for * the specified collections of numbers: <code>y = mx</code>. * * @param x The collection of x coordinates. * @param y The collection of y coordiantes. * @return The slope of the corresponding line model. * @throws IllegalArgumentException Signals that the two collections * are empty or not of the same size. */ public static double fitSlope(Statistics x, Statistics y) { if (x.size() != y.size()) { throw new IllegalArgumentException("Inconsistent collection sizes"); } else if (0 == x.size()) { throw new IllegalArgumentException("Empty collections"); } double xMean = 0; double yMean = 0; double dx2Mean = 0; double dxdyMean = 0; final int size = x.size(); for (int i=0; i<size; i++) { xMean += (x.get(i) - xMean) / (i + 1); yMean += (y.get(i) - yMean) / (i + 1); } for (int i=0; i<size; i++) { final double dx = x.get(i) - xMean; final double dy = y.get(i) - yMean; dx2Mean += (dx * dx - dx2Mean) / (i + 1); dxdyMean += (dx * dy - dxdyMean) / (i + 1); } return (xMean * yMean + dxdyMean) / (xMean * xMean + dx2Mean); } }