001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.commons.statistics.descriptive; 018 019/** 020 * Computes the standard deviation of the available values. The default implementation uses the 021 * following definition of the <em>sample standard deviation</em>: 022 * 023 * <p>\[ \sqrt{ \tfrac{1}{n-1} \sum_{i=1}^n (x_i-\overline{x})^2 } \] 024 * 025 * <p>where \( \overline{x} \) is the sample mean, and \( n \) is the number of samples. 026 * 027 * <ul> 028 * <li>The result is {@code NaN} if no values are added. 029 * <li>The result is zero if there is one value in the data set. 030 * </ul> 031 * 032 * <p>The use of the term \( n − 1 \) is called Bessel's correction. Omitting the square root, 033 * this provides an unbiased estimator of the variance of a hypothetical infinite population. If the 034 * {@link #setBiased(boolean) biased} option is enabled the normalisation factor is 035 * changed to \( \frac{1}{n} \) for a biased estimator of the <em>sample variance</em>. 036 * Note however that square root is a concave function and thus introduces negative bias 037 * (by Jensen's inequality), which depends on the distribution, and thus the corrected sample 038 * standard deviation (using Bessel's correction) is less biased, but still biased. 039 * 040 * <p>The implementation uses an exact integer sum to compute the scaled (by \( n \)) 041 * sum of squared deviations from the mean; this is normalised by the scaled correction factor. 042 * 043 * <p>\[ \frac {n \times \sum_{i=1}^n x_i^2 - (\sum_{i=1}^n x_i)^2}{n \times (n - 1)} \] 044 * 045 * <p>Supports up to 2<sup>63</sup> (exclusive) observations. 046 * This implementation does not check for overflow of the count. 047 * 048 * <p>This class is designed to work with (though does not require) 049 * {@linkplain java.util.stream streams}. 050 * 051 * <p><strong>This implementation is not thread safe.</strong> 052 * If multiple threads access an instance of this class concurrently, 053 * and at least one of the threads invokes the {@link java.util.function.LongConsumer#accept(long) accept} or 054 * {@link StatisticAccumulator#combine(StatisticResult) combine} method, it must be synchronized externally. 055 * 056 * <p>However, it is safe to use {@link java.util.function.LongConsumer#accept(long) accept} 057 * and {@link StatisticAccumulator#combine(StatisticResult) combine} 058 * as {@code accumulator} and {@code combiner} functions of 059 * {@link java.util.stream.Collector Collector} on a parallel stream, 060 * because the parallel implementation of {@link java.util.stream.Stream#collect Stream.collect()} 061 * provides the necessary partitioning, isolation, and merging of results for 062 * safe and efficient parallel execution. 063 * 064 * @see <a href="https://en.wikipedia.org/wiki/Standard_deviation">Standard deviation (Wikipedia)</a> 065 * @see <a href="https://en.wikipedia.org/wiki/Bessel%27s_correction">Bessel's correction</a> 066 * @see <a href="https://en.wikipedia.org/wiki/Jensen%27s_inequality">Jensen's inequality</a> 067 * @see LongVariance 068 * @since 1.1 069 */ 070public final class LongStandardDeviation implements LongStatistic, StatisticAccumulator<LongStandardDeviation> { 071 072 /** Sum of the squared values. */ 073 private final UInt192 sumSq; 074 /** Sum of the values. */ 075 private final Int128 sum; 076 /** Count of values that have been added. */ 077 private long n; 078 079 /** Flag to control if the statistic is biased, or should use a bias correction. */ 080 private boolean biased; 081 082 /** 083 * Create an instance. 084 */ 085 private LongStandardDeviation() { 086 this(UInt192.create(), Int128.create(), 0); 087 } 088 089 /** 090 * Create an instance. 091 * 092 * @param sumSq Sum of the squared values. 093 * @param sum Sum of the values. 094 * @param n Count of values that have been added. 095 */ 096 private LongStandardDeviation(UInt192 sumSq, Int128 sum, int n) { 097 this.sumSq = sumSq; 098 this.sum = sum; 099 this.n = n; 100 } 101 102 /** 103 * Creates an instance. 104 * 105 * <p>The initial result is {@code NaN}. 106 * 107 * @return {@code LongStandardDeviation} instance. 108 */ 109 public static LongStandardDeviation create() { 110 return new LongStandardDeviation(); 111 } 112 113 /** 114 * Returns an instance populated using the input {@code values}. 115 * 116 * @param values Values. 117 * @return {@code LongStandardDeviation} instance. 118 */ 119 public static LongStandardDeviation of(long... values) { 120 // Note: Arrays could be processed using specialised counts knowing the maximum limit 121 // for an array is 2^31 values. Requires a UInt160. 122 123 final Int128 s = Int128.create(); 124 final UInt192 ss = UInt192.create(); 125 for (final long x : values) { 126 s.add(x); 127 ss.addSquare(x); 128 } 129 return new LongStandardDeviation(ss, s, values.length); 130 } 131 132 /** 133 * Updates the state of the statistic to reflect the addition of {@code value}. 134 * 135 * @param value Value. 136 */ 137 @Override 138 public void accept(long value) { 139 sumSq.addSquare(value); 140 sum.add(value); 141 n++; 142 } 143 144 /** 145 * Gets the standard deviation of all input values. 146 * 147 * <p>When no values have been added, the result is {@code NaN}. 148 * 149 * @return standard deviation of all values. 150 */ 151 @Override 152 public double getAsDouble() { 153 return LongVariance.computeVarianceOrStd(sumSq, sum, n, biased, true); 154 } 155 156 @Override 157 public LongStandardDeviation combine(LongStandardDeviation other) { 158 sumSq.add(other.sumSq); 159 sum.add(other.sum); 160 n += other.n; 161 return this; 162 } 163 164 /** 165 * Sets the value of the biased flag. The default value is {@code false}. The bias 166 * term refers to the computation of the variance; the standard deviation is returned 167 * as the square root of the biased or unbiased <em>sample variance</em>. For further 168 * details see {@link LongVariance#setBiased(boolean) LongStandardDeviationVariance.setBiased}. 169 * 170 * <p>This flag only controls the final computation of the statistic. The value of 171 * this flag will not affect compatibility between instances during a 172 * {@link #combine(LongStandardDeviation) combine} operation. 173 * 174 * @param v Value. 175 * @return {@code this} instance 176 * @see LongStandardDeviation#setBiased(boolean) 177 */ 178 179 public LongStandardDeviation setBiased(boolean v) { 180 biased = v; 181 return this; 182 } 183}