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 }