View Javadoc

    1   /*
    2    * Copyright 2004 The Apache Software Foundation.
    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
    17  package org.apache.commons.math.distribution;
    18
    19  import java.io.Serializable;
    20
    21  import org.apache.commons.math.MathException;
    22  import org.apache.commons.math.special.Erf;
    23
    24  /***
    25   * Default implementation of
    26   * {@link org.apache.commons.math.distribution.NormalDistribution}.
    27   *
    28   * @version $Revision: 1.13 $ $Date: 2004/07/24 21:41:36 $
    29   */
    30  public class NormalDistributionImpl extends AbstractContinuousDistribution
    31  		implements NormalDistribution, Serializable {
    32
    33      /*** Serializable version identifier */
    34      static final long serialVersionUID = 8589540077390120676L;
    35
    36      /*** The mean of this distribution. */
    37  	private double mean = 0;
    38
    39      /*** The standard deviation of this distribution. */
    40  	private double standardDeviation = 1;
    41
    42  	/***
    43  	 * Create a normal distribution using the given mean and standard deviation.
    44  	 * @param mean mean for this distribution
    45  	 * @param sd standard deviation for this distribution
    46  	 */
    47  	public NormalDistributionImpl(double mean, double sd){
    48  		super();
    49  		setMean(mean);
    50  		setStandardDeviation(sd);
    51  	}
    52
    53  	/***
    54  	 * Creates normal distribution with the mean equal to zero and standard
    55  	 * deviation equal to one.
    56  	 */
    57  	public NormalDistributionImpl(){
    58  		this(0.0, 1.0);
    59  	}
    60
    61  	/***
    62  	 * Access the mean.
    63  	 * @return mean for this distribution
    64  	 */
    65  	public double getMean() {
    66  		return mean;
    67  	}
    68
    69  	/***
    70  	 * Modify the mean.
    71  	 * @param mean for this distribution
    72  	 */
    73  	public void setMean(double mean) {
    74  		this.mean = mean;
    75  	}
    76
    77  	/***
    78  	 * Access the standard deviation.
    79  	 * @return standard deviation for this distribution
    80  	 */
    81  	public double getStandardDeviation() {
    82  		return standardDeviation;
    83  	}
    84
    85  	/***
    86  	 * Modify the standard deviation.
    87  	 * @param sd standard deviation for this distribution
    88       * @throws IllegalArgumentException if <code>sd</code> is not positive.
    89  	 */
    90  	public void setStandardDeviation(double sd) {
    91  		if (sd <= 0.0) {
    92  			throw new IllegalArgumentException(
    93                  "Standard deviation must be positive.");
    94  		}
    95  		standardDeviation = sd;
    96  	}
    97
    98  	/***
    99  	 * For this disbution, X, this method returns P(X &lt; <code>x</code>).
    100 	 * @param x the value at which the CDF is evaluated.
    101 	 * @return CDF evaluted at <code>x</code>.
    102 	 * @throws MathException if the algorithm fails to converge.
    103 	 */
    104 	public double cumulativeProbability(double x) throws MathException {
    105         return 0.5 * (1.0 + Erf.erf((x - mean) /
    106                 (standardDeviation * Math.sqrt(2.0))));
    107 	}
    108
    109     /***
    110      * For this distribution, X, this method returns the critical point x, such
    111      * that P(X &lt; x) = <code>p</code>.
    112      * <p>
    113      * Returns <code>Double.NEGATIVE_INFINITY</code> for p=0 and
    114      * <code>Double.POSITIVE_INFINITY</code> for p=1.
    115      *
    116      * @param p the desired probability
    117      * @return x, such that P(X &lt; x) = <code>p</code>
    118      * @throws MathException if the inverse cumulative probability can not be
    119      *         computed due to convergence or other numerical errors.
    120      * @throws IllegalArgumentException if <code>p</code> is not a valid
    121      *         probability.
    122      */
    123     public double inverseCumulativeProbability(final double p)
    124     throws MathException {
    125         if (p == 0) {
    126             return Double.NEGATIVE_INFINITY;
    127         }
    128         if (p == 1) {
    129             return Double.POSITIVE_INFINITY;
    130         }
    131         return super.inverseCumulativeProbability(p);
    132     }
    133
    134 	/***
    135 	 * Access the domain value lower bound, based on <code>p</code>, used to
    136 	 * bracket a CDF root.  This method is used by
    137 	 * {@link #inverseCumulativeProbability(double)} to find critical values.
    138 	 *
    139 	 * @param p the desired probability for the critical value
    140 	 * @return domain value lower bound, i.e.
    141 	 *         P(X &lt; <i>lower bound</i>) &lt; <code>p</code>
    142 	 */
    143 	protected double getDomainLowerBound(double p) {
    144         double ret;
    145
    146         if (p < .5) {
    147             ret = -Double.MAX_VALUE;
    148         } else {
    149             ret = getMean();
    150         }
    151
    152         return ret;
    153     }
    154
    155 	/***
    156 	 * Access the domain value upper bound, based on <code>p</code>, used to
    157 	 * bracket a CDF root.  This method is used by
    158 	 * {@link #inverseCumulativeProbability(double)} to find critical values.
    159 	 *
    160 	 * @param p the desired probability for the critical value
    161 	 * @return domain value upper bound, i.e.
    162 	 *         P(X &lt; <i>upper bound</i>) &gt; <code>p</code>
    163 	 */
    164 	protected double getDomainUpperBound(double p) {
    165         double ret;
    166
    167         if (p < .5) {
    168             ret = getMean();
    169         } else {
    170             ret = Double.MAX_VALUE;
    171         }
    172
    173         return ret;
    174     }
    175
    176 	/***
    177 	 * Access the initial domain value, based on <code>p</code>, used to
    178 	 * bracket a CDF root.  This method is used by
    179 	 * {@link #inverseCumulativeProbability(double)} to find critical values.
    180 	 *
    181 	 * @param p the desired probability for the critical value
    182 	 * @return initial domain value
    183 	 */
    184 	protected double getInitialDomain(double p) {
    185         double ret;
    186
    187         if (p < .5) {
    188             ret = getMean() - getStandardDeviation();
    189         } else if (p > .5) {
    190             ret = getMean() + getStandardDeviation();
    191         } else {
    192             ret = getMean();
    193         }
    194
    195         return ret;
    196 	}
    197 }