// ================================================================================================= // Copyright 2011 Twitter, Inc. // ------------------------------------------------------------------------------------------------- // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this work except in compliance with the License. // You may obtain a copy of the License in the LICENSE file, or 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. // ================================================================================================= /** ************************************************************************ ** Summize ** This work protected by US Copyright Law and contains proprietary and ** confidential trade secrets. ** (c) Copyright 2007 Summize, ALL RIGHTS RESERVED. ** ************************************************************************/ package com.twitter.common.util; //*************************************************************** // import java.io.DataInput; import java.io.DataInputStream; import java.io.DataOutput; import java.io.DataOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.Serializable; import java.text.NumberFormat; /** * This class is designed to provide basic statistics collection. * For each instance of this object statistics and be added to it * then the sum, mean, std dev, min and max can be gathered at the * end. To reuse this object, a clear method can be called to reset * the statistics. * * @author Abdur Chowdhury */ public class Stat implements Serializable { /** * Add a number to the statistics collector. * doubles are used for all collections. * * @param int - number added to the statistics. * @return void */ public void addNumber(int x) { addNumber((double) x); } /** * Add a number to the statistics collector. * doubles are used for all collections. * * @param float - number added to the statistics. * @return void */ public void addNumber(float x) { addNumber((double) x); } /** * Add a number to the statistics collector. * doubles are used for all collections. * * @param double - number added to the statistics. * @return void */ public synchronized void addNumber(double x) { if (_max < x) { _max = x; } if (_min > x) { _min = x; } _sum += x; _sumOfSq += (x * x); _number++; return; } /** * Clear the statistics counters... * * @param void * @return void */ public void clear() { _max = 0; _min = Double.MAX_VALUE; _number = 0; _mean = 0; _stdDev = 0; _sum = 0; _sumOfSq = 0; } /** * Create a string representation of the * statistics collected so far. NOTE this * is formated and may not suit all needs * and thus the user should just call the * needed methods to get mean, std dev, etc. * and format the data as needed. * * @param void * @return String - Java string formated out put * of results. */ public String toString() { return toString(false); } /** * Create a string representation of the * statistics collected so far. The results * are formated in percentage format if * passed in true, otherwise the results * are the same as the toString call. NOTE this * is formated and may not suit all needs * and thus the user should just call the * needed methods to get mean, std dev, etc. * and format the data as needed. * * @param boolean - Format as percentages if set to true. * @return String - Java string formated out put * of results. */ public String toString(boolean percent) { calculate(); NumberFormat nf = NumberFormat.getInstance(); nf.setMaximumFractionDigits(4); if (_number > 1) { StringBuffer results = new StringBuffer(); if (percent) { results.append("Number:" + nf.format(_number * 100) + "%"); } else { results.append("Number:" + nf.format(_number)); } if (percent) { results.append(" Max:" + nf.format(_max * 100) + "%"); } else { results.append(" Max:" + nf.format(_max)); } if (percent) { results.append(" Min:" + nf.format(_min * 100) + "%"); } else { results.append(" Min:" + nf.format(_min)); } if (percent) { results.append(" Mean:" + nf.format(_mean * 100) + "%"); } else { results.append(" Mean:" + nf.format(_mean)); } results.append(" Sum:" + nf.format(_sum)); results.append(" STD:" + nf.format(_stdDev)); return results.toString(); } else if (_number == 1) { if (percent) { return ("Number:" + nf.format(_sum * 100) + "%"); } else { return ("Number:" + nf.format(_sum)); } } else { return ("Number: N/A"); } } private void calculate() { getMean(); getStandardDev(); } /** * Get the max data element added to the statistics * object so far. * * @param void * @return double - Maximum entry added so far. */ public double getMax() { return _max; } /** * Get the min data element added to the statistics * object so far. * * @param void * @return double - Min entry added so far. */ public double getMin() { return _min; } /** * Get the number of data elements added to the statistics * object so far. * * @param void * @return double - Number of entries added so far. */ public long getNumberOfElements() { return _number; } /** * Get the average or mean of data elements added to the * statistics object so far. * * @param void * @return double - Mean of entries added so far. */ public double getMean() { if (_number > 0) { _mean = _sum / _number; } return _mean; } /** * Get the ratio of the sum of elements divided by the number * of elements added * 100 * * @param void * @return double - Percent of entries added so far. */ public double getPercent() { if (_number > 0) { _mean = _sum / _number; } _mean = _mean * 100; return _mean; } /** * Get the sum or mean of data elements added to the * statistics object so far. * * @param void * @return double - Sum of entries added so far. */ public double getSum() { return _sum; } /** * Get the sum of the squares of the data elements added * to the statistics object so far. * * @param void * @return double - Sum of the squares of the entries added so far. */ public double getSumOfSq() { return _sumOfSq; } /** * Get the standard deviation of the data elements added * to the statistics object so far. * * @param void * @return double - Sum of the standard deviation of the entries added so far. */ public double getStandardDev() { if (_number > 1) { _stdDev = Math.sqrt((_sumOfSq - ((_sum * _sum) / _number)) / (_number - 1)); } return _stdDev; } /** * Read the data from the inputstream so it can be used to populate * the current objects state. * * @param InputStream - java.io.InputStream to write to. * @return void * @throws IOException */ public void readFromDataInput(InputStream in) throws IOException { DataInput di = new DataInputStream(in); readFromDataInput(di); return; } /** * Read the data from the datainput so it can be used to populate * the current objects state. * * @param InputStream - java.io.InputStream to write to. * @return void * @throws IOException */ public void readFromDataInput(DataInput in) throws IOException { _max = in.readDouble(); _min = in.readDouble(); _number = in.readLong(); _mean = in.readDouble(); _stdDev = in.readDouble(); _sum = in.readDouble(); _sumOfSq = in.readDouble(); return; } /** * Write the data to the output steam so it can be streamed to an * other process, wire or storage median in a format that another Stats * object can read. * * @param OutputStream - java.io.OutputStream to write to. * @return void * @throws IOException */ public void writeToDataOutput(OutputStream out) throws IOException { DataOutput dout = new DataOutputStream(out); writeToDataOutput(dout); return; } /** * Write the data to the data output object so it can be written to an * other process, wire or storage median in a format that another Stats * object can read. * * @param InputStream - java.io.InputStream to write to. * @return void * @throws IOException */ public void writeToDataOutput(DataOutput out) throws IOException { out.writeDouble(_max); out.writeDouble(_min); out.writeLong(_number); out.writeDouble(_mean); out.writeDouble(_stdDev); out.writeDouble(_sum); out.writeDouble(_sumOfSq); return; } // ************************************ private static final long serialVersionUID = 1L; private double _max = 0 ; private double _min = Double.MAX_VALUE ; private long _number = 0 ; private double _mean = 0 ; private double _stdDev = 0 ; private double _sum = 0 ; private double _sumOfSq ; }