1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.apache.commons.math.stat.descriptive.moment;
17
18 import org.apache.commons.math.stat.descriptive.AbstractStorelessUnivariateStatistic;
19 import org.apache.commons.math.stat.descriptive.summary.SumOfLogs;
20
21 /**
22 * Returns the <a href="http://www.xycoon.com/geometric_mean.htm">
23 * geometric mean </a> of the available values.
24 * <p>
25 * Uses a {@link SumOfLogs} instance to compute sum of logs and returns
26 * <code> exp( 1/n (sum of logs) ).</code> Therefore,
27 * <ul>
28 * <li>If any of values are < 0, the result is <code>NaN.</code></li>
29 * <li>If all values are non-negative and less than
30 * <code>Double.POSITIVE_INFINITY</code>, but at least one value is 0, the
31 * result is <code>0.</code></li>
32 * <li>If both <code>Double.POSITIVE_INFINITY</code> and
33 * <code>Double.NEGATIVE_INFINITY</code> are among the values, the result is
34 * <code>NaN.</code></li>
35 * </ul>
36 * <p>
37 * <strong>Note that this implementation is not synchronized.</strong> If
38 * multiple threads access an instance of this class concurrently, and at least
39 * one of the threads invokes the <code>increment()</code> or
40 * <code>clear()</code> method, it must be synchronized externally.
41 *
42 *
43 * @version $Revision: 348519 $ $Date: 2005-11-23 12:12:18 -0700 (Wed, 23 Nov 2005) $
44 */
45 public class GeometricMean extends AbstractStorelessUnivariateStatistic {
46
47 /** Serializable version identifier */
48 private static final long serialVersionUID = -8178734905303459453L;
49
50 /** Wrapped SumOfLogs instance */
51 private SumOfLogs sumOfLogs;
52
53 /**
54 * Create a GeometricMean instance
55 */
56 public GeometricMean() {
57 sumOfLogs = new SumOfLogs();
58 }
59
60 /**
61 * @see org.apache.commons.math.stat.descriptive.StorelessUnivariateStatistic#increment(double)
62 */
63 public void increment(final double d) {
64 sumOfLogs.increment(d);
65 }
66
67 /**
68 * @see org.apache.commons.math.stat.descriptive.StorelessUnivariateStatistic#getResult()
69 */
70 public double getResult() {
71 if (sumOfLogs.getN() > 0) {
72 return Math.exp(sumOfLogs.getResult() / (double) sumOfLogs.getN());
73 } else {
74 return Double.NaN;
75 }
76 }
77
78 /**
79 * @see org.apache.commons.math.stat.descriptive.StorelessUnivariateStatistic#clear()
80 */
81 public void clear() {
82 sumOfLogs.clear();
83 }
84
85 /**
86 * Returns the geometric mean of the entries in the specified portion
87 * of the input array.
88 * <p>
89 * See {@link GeometricMean} for details on the computing algorithm.
90 * <p>
91 * Throws <code>IllegalArgumentException</code> if the array is null.
92 *
93 * @param values input array containing the values
94 * @param begin first array element to include
95 * @param length the number of elements to include
96 * @return the geometric mean or Double.NaN if length = 0 or
97 * any of the values are <= 0.
98 * @throws IllegalArgumentException if the input array is null or the array
99 * index parameters are not valid
100 */
101 public double evaluate(
102 final double[] values, final int begin, final int length) {
103 return Math.exp(
104 sumOfLogs.evaluate(values, begin, length) / (double) length);
105 }
106
107 /**
108 * @see org.apache.commons.math.stat.descriptive.StorelessUnivariateStatistic#getN()
109 */
110 public long getN() {
111 return sumOfLogs.getN();
112 }
113
114 }