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 */ 017 package org.apache.commons.math3.distribution; 018 019 import org.apache.commons.math3.exception.OutOfRangeException; 020 import org.apache.commons.math3.exception.NotPositiveException; 021 import org.apache.commons.math3.exception.util.LocalizedFormats; 022 import org.apache.commons.math3.special.Beta; 023 import org.apache.commons.math3.util.FastMath; 024 import org.apache.commons.math3.random.RandomGenerator; 025 import org.apache.commons.math3.random.Well19937c; 026 027 /** 028 * Implementation of the binomial distribution. 029 * 030 * @see <a href="http://en.wikipedia.org/wiki/Binomial_distribution">Binomial distribution (Wikipedia)</a> 031 * @see <a href="http://mathworld.wolfram.com/BinomialDistribution.html">Binomial Distribution (MathWorld)</a> 032 * @version $Id: BinomialDistribution.java 1416643 2012-12-03 19:37:14Z tn $ 033 */ 034 public class BinomialDistribution extends AbstractIntegerDistribution { 035 /** Serializable version identifier. */ 036 private static final long serialVersionUID = 6751309484392813623L; 037 /** The number of trials. */ 038 private final int numberOfTrials; 039 /** The probability of success. */ 040 private final double probabilityOfSuccess; 041 042 /** 043 * Create a binomial distribution with the given number of trials and 044 * probability of success. 045 * 046 * @param trials Number of trials. 047 * @param p Probability of success. 048 * @throws NotPositiveException if {@code trials < 0}. 049 * @throws OutOfRangeException if {@code p < 0} or {@code p > 1}. 050 */ 051 public BinomialDistribution(int trials, double p) { 052 this(new Well19937c(), trials, p); 053 } 054 055 /** 056 * Creates a binomial distribution. 057 * 058 * @param rng Random number generator. 059 * @param trials Number of trials. 060 * @param p Probability of success. 061 * @throws NotPositiveException if {@code trials < 0}. 062 * @throws OutOfRangeException if {@code p < 0} or {@code p > 1}. 063 * @since 3.1 064 */ 065 public BinomialDistribution(RandomGenerator rng, 066 int trials, 067 double p) { 068 super(rng); 069 070 if (trials < 0) { 071 throw new NotPositiveException(LocalizedFormats.NUMBER_OF_TRIALS, 072 trials); 073 } 074 if (p < 0 || p > 1) { 075 throw new OutOfRangeException(p, 0, 1); 076 } 077 078 probabilityOfSuccess = p; 079 numberOfTrials = trials; 080 } 081 082 /** 083 * Access the number of trials for this distribution. 084 * 085 * @return the number of trials. 086 */ 087 public int getNumberOfTrials() { 088 return numberOfTrials; 089 } 090 091 /** 092 * Access the probability of success for this distribution. 093 * 094 * @return the probability of success. 095 */ 096 public double getProbabilityOfSuccess() { 097 return probabilityOfSuccess; 098 } 099 100 /** {@inheritDoc} */ 101 public double probability(int x) { 102 double ret; 103 if (x < 0 || x > numberOfTrials) { 104 ret = 0.0; 105 } else { 106 ret = FastMath.exp(SaddlePointExpansion.logBinomialProbability(x, 107 numberOfTrials, probabilityOfSuccess, 108 1.0 - probabilityOfSuccess)); 109 } 110 return ret; 111 } 112 113 /** {@inheritDoc} */ 114 public double cumulativeProbability(int x) { 115 double ret; 116 if (x < 0) { 117 ret = 0.0; 118 } else if (x >= numberOfTrials) { 119 ret = 1.0; 120 } else { 121 ret = 1.0 - Beta.regularizedBeta(probabilityOfSuccess, 122 x + 1.0, numberOfTrials - x); 123 } 124 return ret; 125 } 126 127 /** 128 * {@inheritDoc} 129 * 130 * For {@code n} trials and probability parameter {@code p}, the mean is 131 * {@code n * p}. 132 */ 133 public double getNumericalMean() { 134 return numberOfTrials * probabilityOfSuccess; 135 } 136 137 /** 138 * {@inheritDoc} 139 * 140 * For {@code n} trials and probability parameter {@code p}, the variance is 141 * {@code n * p * (1 - p)}. 142 */ 143 public double getNumericalVariance() { 144 final double p = probabilityOfSuccess; 145 return numberOfTrials * p * (1 - p); 146 } 147 148 /** 149 * {@inheritDoc} 150 * 151 * The lower bound of the support is always 0 except for the probability 152 * parameter {@code p = 1}. 153 * 154 * @return lower bound of the support (0 or the number of trials) 155 */ 156 public int getSupportLowerBound() { 157 return probabilityOfSuccess < 1.0 ? 0 : numberOfTrials; 158 } 159 160 /** 161 * {@inheritDoc} 162 * 163 * The upper bound of the support is the number of trials except for the 164 * probability parameter {@code p = 0}. 165 * 166 * @return upper bound of the support (number of trials or 0) 167 */ 168 public int getSupportUpperBound() { 169 return probabilityOfSuccess > 0.0 ? numberOfTrials : 0; 170 } 171 172 /** 173 * {@inheritDoc} 174 * 175 * The support of this distribution is connected. 176 * 177 * @return {@code true} 178 */ 179 public boolean isSupportConnected() { 180 return true; 181 } 182 }