1 /* 2 * Copyright 2013 University of Glasgow. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package broadwick.statistics; 17 18 import java.io.Serializable; 19 import java.text.DecimalFormat; 20 21 /** 22 * This class collects data values and calculates their mean and variance. 23 */ 24 public class Samples implements Serializable { 25 26 /** 27 * Empty object where the internal values are initialised to 0. Getting any statistics from this object will result 28 * in a divide by zero exceptions since there are zero elements in the accumulator. 29 */ 30 public Samples() { 31 sum = 0.0; 32 sumSqr = 0.0; 33 product = 0.0; 34 sumInv = 0.0; 35 total = 0; 36 } 37 38 /** 39 * Initialise the internal values of the accumulator with the argument given. 40 * @param value the value to initialise the internal variables. 41 */ 42 public Samples(final double value) { 43 sum = value; 44 sumSqr = value * value; 45 product = value; 46 sumInv = 1.0 / value; 47 total = 1; 48 } 49 50 /** 51 * Add an observable (value) to the accumulator. 52 * @param value add the value to the accumulated values. 53 * @return the current accumulator object. 54 */ 55 public final Samples add(final double value) { 56 sum += value; 57 sumSqr += (value * value); 58 product = (product == 0) ? value : product * value; 59 sumInv += (1.0 / value); 60 total++; 61 return this; 62 } 63 64 /** 65 * Add the contents of anther accumulator to this accumulator. 66 * @param value add the value to the accumulated values. 67 * @return the current accumulator object. 68 */ 69 public final Samples add(final Samples value) { 70 sum += value.sum; 71 sumSqr += value.sumSqr; 72 product += value.product; 73 sumInv += value.sumInv; 74 total += value.getSize(); 75 return this; 76 } 77 78 /** 79 * Obtain the mean of the set of observables in the accumulator. 80 * @return double the mean in the observed values. 81 */ 82 public final double getMean() { 83 final int tot = (total == 0) ? 1 : total; 84 return sum / tot; 85 } 86 87 /** 88 * Obtain the root mean square of the set of observables in the accumulator. 89 * @return double the root mean square in the observed values. 90 */ 91 public final double getRootMeanSquare() { 92 final int tot = (total == 0) ? 1 : total; 93 return Math.sqrt(sumSqr / tot); 94 } 95 96 /** 97 * Obtain the geometric mean of the set of observables in the accumulator. 98 * @return double the geometric mean in the observed values. 99 */ 100 public final double getGeometricMean() { 101 final int tot = (total == 0) ? 1 : total; 102 return Math.pow(product, 1.0 / tot); 103 } 104 105 /** 106 * Obtain the harmonic mean of the set of observables in the accumulator. 107 * @return double the harmonic mean in the observed values. 108 */ 109 public final double getHarmonicMean() { 110 final double inv = (sumInv == 0) ? 1 : sumInv; 111 return total / inv; 112 } 113 114 /** 115 * Get the sum of the values held in the accumulator. 116 * @return the sum of all the values added to the accumulator. 117 */ 118 public final double getSum() { 119 return sum; 120 } 121 122 /** 123 * Get the number of items added to the Accumulator. 124 * @return the number of items added to the Accumulator. 125 */ 126 public final int getSize() { 127 return total; 128 } 129 130 /** 131 * Default sample variance implementation based on the second moment \f$ M_n^{(2)} \f$ moment<2>, mean and count. 132 * \f[ \sigma_n^2 = M_n^{(2)} - \mu_n^2. \f] where \f[ \mu_n = \frac{1}{n} \sum_{i = 1}^n x_i. \f] is the estimate 133 * of the sample mean and \f$n\f$ is the number of samples. 134 * @return double the variance of the observed values. 135 */ 136 public final double getVariance() { 137 final int tot = (total == 0) ? 1 : total; 138 final double mn = sum / tot; 139 140 return (sumSqr / tot - (mn * mn)) / tot; 141 } 142 143 /** 144 * Obtain the standard deviation (error in the mean) of the set of observeables in the accumulator. 145 * @return double the standard deviation in the observed values. 146 */ 147 public final double getStdDev() { 148 return Math.sqrt(this.getVariance()); 149 } 150 151 /** 152 * Clear the contents of the accumulator. Sets all the internal counts back to zero. 153 */ 154 public final void clear() { 155 sum = 0.0; 156 sumSqr = 0.0; 157 product = 0.0; 158 sumInv = 0.0; 159 total = 0; 160 } 161 162 /** 163 * Get a tab delimited string of the mean and standard deviation of the values in the accumulator. 164 * @return a string in the form "\tmean\tdev" 165 */ 166 public final String getSummary() { 167 final StringBuilder sb = new StringBuilder(10); 168 sb.append("\t").append(new DecimalFormat("0.0000E0").format(getMean())); 169 sb.append("\t").append(new DecimalFormat("0.0000E0").format(getStdDev())); 170 return sb.toString(); 171 } 172 173 private double sum = 0.0; // The sum of all values added to the accumulator. 174 private double sumSqr = 0.0; // The sum of all values squared added to the accumulator. 175 private double product = 0.0; // The product of all values added to the accumulator. 176 private double sumInv = 0.0; // The sum of the 1/value. 177 private int total = 0; // The total number of values added to the accumulator. 178 }