/* * Copyright to the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.rioproject.watch; import java.util.*; /** * Class Statistics implements basic statistical formulae. */ public class Statistics { /** the collection of values */ private final Vector<Double> v = new Vector<Double>(); /** no arg constructor */ public Statistics() { super(); } /** * Construct a new Statistics * * @param values initial values for new instance */ public Statistics(Iterable<Double> values) { if(values==null) throw new IllegalArgumentException("values is null"); for(Double d : values) { v.add(d); } } /** * Removes all of the values in the internal collection. */ public void clearAll() { v.clear(); } /** * Number of values in collection of values * * @return int number of values */ public int count() { return v.size(); } /** * Get largest value in collection of values * * @return double largest value */ public double max() { if(v.isEmpty()) return(0.0D / 0.0D); //NaN return Collections.max(v); } /** * Get smallest value in collection of values * * @return double smallest value */ public double min() { if(v.isEmpty()) return(0.0D / 0.0D); //NaN return Collections.min(v); } /** * Get the average value in the collection of values * * @return double the average value in collection */ public double mean() { if(v.isEmpty()) return(0.0D / 0.0D); //NaN double sum = sum(); return sum / (double) v.size(); } /** * Get the median in the collection of values * * @return double the middle value in the collection of values */ public double median() { if(v.isEmpty()) return(0.0D / 0.0D); //NaN double result; Vector<Double> sortedV = sorted(); Double[] dArray = new Double[v.size()]; dArray = sortedV.toArray(dArray); if(dArray.length % 2 != 0 && dArray.length > 0) { // length is odd int k = (dArray.length -1) / 2; // middle index result = dArray[k]; } else { // length is even, take avg of two mid vals int k = (dArray.length-1) / 2; // low middle index /* average of low mid val and low mid idx+1 val */ result = (dArray[k] + dArray[k + 1]) / 2D; } return result; } /** * Get the mode * * @return double the value with the highest number of occurrences */ public double mode() { if(v.isEmpty()) return(0.0D / 0.0D); //NaN return (Double) mode0(true); } /** * Get the occurrences of the mode * * @return int count of the value with the highest number of occurrences */ public int modeOccurrenceCount() { if(v.isEmpty()) return(0); return (Integer) mode0(false); } /** * Get the mode or occurrences of the mode * * @return Object the value with the highest number of occurrences * @param returnMode boolean true to return the mode, false occurrences */ private Object mode0(boolean returnMode) { Map<Object, Integer> hashTable = new Hashtable<Object, Integer>(v.size(), 1.0f); Object obj; Integer occurrences = 0; int modeCnt; Double mode = 0.0D; for (Double aV : v) { obj = aV; if (hashTable.containsKey(obj)) { modeCnt = (hashTable.get(obj)) + 1; } else { modeCnt = 1; } hashTable.put(obj, modeCnt); } if(returnMode) { return mode; } else { return occurrences; } } /** * Get the range * * @return double the difference between the min and max */ public double range() { if(v.isEmpty()) return(0.0D / 0.0D); //NaN else return max() - min(); } /** * Get the standard deviation * * @return double the dispersion from the mean */ public double standardDeviation() { if(v.isEmpty()) { return(0.0D / 0.0D); //NaN } if(v.size() == 1) { // Need to return 0 explicitly because otherwise there would // be division by zero return 0; } double sum = sum(); double sumOfSquares = 0.0D; for (Double aV : v) { sumOfSquares += Math.pow((aV), 2D); } return Math.sqrt((sumOfSquares - Math.pow(sum, 2d) / (double) v.size()) / (double)(v.size() - 1)); } public Vector getValues() { return (Vector)v.clone(); } public void addValue(Double double1) { if(double1==null) throw new IllegalArgumentException("value is null"); v.addElement(double1); } public void addValue(double d) { v.addElement(d); } public void setValues(Iterable<Double> vals) { if(vals==null) throw new IllegalArgumentException("vector is null"); v.clear(); for(Double d : vals) v.add(d); } public void setValues(Calculable[] calcs) { if(calcs==null) throw new IllegalArgumentException("calcs is null"); v.clear(); for(Calculable calc : calcs) v.add(calc.getValue()); } /** * Remove value * * @param d the double to remove * @param removeAll false remove first occurrence; true remove all */ public void removeValues(double d, boolean removeAll) { removeValues((Double) d, removeAll); } /** * Remove value * * @param double1 the Double to remove * @param removeAll false remove first occurrence; true remove all */ public void removeValues(Double double1, boolean removeAll) { if(double1==null) throw new IllegalArgumentException("value is null"); if(removeAll) { Vector<Double> toRemove = new Vector<Double>(1); toRemove.add(double1); v.removeAll(toRemove); } else { v.removeElement(double1); } } public void removeValue(int location) { if(location < v.size() && location >= 0) v.removeElementAt(location); } /** * Remove values with a value between double1 and double2 * * @param low the lowest value to remove * @param high the highest value to remove */ public void removeValues(Double low, Double high) { if(low==null) throw new IllegalArgumentException("low is null"); if(high==null) throw new IllegalArgumentException("high is null"); removeValues(low.doubleValue(), high.doubleValue()); } /** * Remove values with a value between double1 and double2 * * @param low the lowest value to remove * @param high the highest value to remove */ public void removeValues(double low, double high) { for(int i = 0; i < v.size(); i++) { if(v.elementAt(i) >= low && v.elementAt(i) <= high) { v.removeElementAt(i); i--; } } } /** * Get the sum of all values * * @return double the sum of all values */ public double sum() { if(v.isEmpty()) return(0.0D / 0.0D); double tot = 0.0D; for (Double aV : v) { tot += aV; } return tot; } private Vector<Double> sorted() { Vector<Double> cpy = new Vector<Double>(); cpy.addAll(v); Collections.sort(cpy); return cpy; } }