1 /* 2 * Copyright 2003-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 package org.apache.commons.math.distribution; 17 18 import java.io.Serializable; 19 20 import org.apache.commons.math.MathException; 21 import org.apache.commons.math.special.Beta; 22 import org.apache.commons.math.util.MathUtils; 23 24 /** 25 * The default implementation of {@link BinomialDistribution}. 26 * 27 * @version $Revision: 348519 $ $Date: 2005-11-23 12:12:18 -0700 (Wed, 23 Nov 2005) $ 28 */ 29 public class BinomialDistributionImpl 30 extends AbstractIntegerDistribution 31 implements BinomialDistribution, Serializable { 32 33 /** Serializable version identifier */ 34 private static final long serialVersionUID = 6751309484392813623L; 35 36 /** The number of trials. */ 37 private int numberOfTrials; 38 39 /** The probability of success. */ 40 private double probabilityOfSuccess; 41 42 /** 43 * Create a binomial distribution with the given number of trials and 44 * probability of success. 45 * @param trials the number of trials. 46 * @param p the probability of success. 47 */ 48 public BinomialDistributionImpl(int trials, double p) { 49 super(); 50 setNumberOfTrials(trials); 51 setProbabilityOfSuccess(p); 52 } 53 54 /** 55 * Access the number of trials for this distribution. 56 * @return the number of trials. 57 */ 58 public int getNumberOfTrials() { 59 return numberOfTrials; 60 } 61 62 /** 63 * Access the probability of success for this distribution. 64 * @return the probability of success. 65 */ 66 public double getProbabilityOfSuccess() { 67 return probabilityOfSuccess; 68 } 69 70 /** 71 * Change the number of trials for this distribution. 72 * @param trials the new number of trials. 73 * @throws IllegalArgumentException if <code>trials</code> is not a valid 74 * number of trials. 75 */ 76 public void setNumberOfTrials(int trials) { 77 if (trials < 0) { 78 throw new IllegalArgumentException("number of trials must be non-negative."); 79 } 80 numberOfTrials = trials; 81 } 82 83 /** 84 * Change the probability of success for this distribution. 85 * @param p the new probability of success. 86 * @throws IllegalArgumentException if <code>p</code> is not a valid 87 * probability. 88 */ 89 public void setProbabilityOfSuccess(double p) { 90 if (p < 0.0 || p > 1.0) { 91 throw new IllegalArgumentException("probability of success must be between 0.0 and 1.0, inclusive."); 92 } 93 probabilityOfSuccess = p; 94 } 95 96 /** 97 * Access the domain value lower bound, based on <code>p</code>, used to 98 * bracket a PDF root. 99 * 100 * @param p the desired probability for the critical value 101 * @return domain value lower bound, i.e. 102 * P(X < <i>lower bound</i>) < <code>p</code> 103 */ 104 protected int getDomainLowerBound(double p) { 105 return -1; 106 } 107 108 /** 109 * Access the domain value upper bound, based on <code>p</code>, used to 110 * bracket a PDF root. 111 * 112 * @param p the desired probability for the critical value 113 * @return domain value upper bound, i.e. 114 * P(X < <i>upper bound</i>) > <code>p</code> 115 */ 116 protected int getDomainUpperBound(double p) { 117 return getNumberOfTrials(); 118 } 119 120 /** 121 * For this distribution, X, this method returns P(X ≤ x). 122 * @param x the value at which the PDF is evaluated. 123 * @return PDF for this distribution. 124 * @throws MathException if the cumulative probability can not be 125 * computed due to convergence or other numerical errors. 126 */ 127 public double cumulativeProbability(int x) throws MathException { 128 double ret; 129 if (x < 0) { 130 ret = 0.0; 131 } else if (x >= getNumberOfTrials()) { 132 ret = 1.0; 133 } else { 134 ret = 135 1.0 - Beta.regularizedBeta( 136 getProbabilityOfSuccess(), 137 x + 1.0, 138 getNumberOfTrials() - x); 139 } 140 return ret; 141 } 142 143 /** 144 * For this disbution, X, this method returns P(X = x). 145 * 146 * @param x the value at which the PMF is evaluated. 147 * @return PMF for this distribution. 148 */ 149 public double probability(int x) { 150 double ret; 151 if (x < 0 || x > getNumberOfTrials()) { 152 ret = 0.0; 153 } else { 154 ret = MathUtils.binomialCoefficientDouble( 155 getNumberOfTrials(), x) * 156 Math.pow(getProbabilityOfSuccess(), x) * 157 Math.pow(1.0 - getProbabilityOfSuccess(), 158 getNumberOfTrials() - x); 159 } 160 return ret; 161 } 162 163 /** 164 * For this distribution, X, this method returns the largest x, such 165 * that P(X ≤ x) ≤ <code>p</code>. 166 * <p> 167 * Returns <code>-1</code> for p=0 and <code>Integer.MAX_VALUE</code> for 168 * p=1. 169 * 170 * @param p the desired probability 171 * @return the largest x such that P(X ≤ x) <= p 172 * @throws MathException if the inverse cumulative probability can not be 173 * computed due to convergence or other numerical errors. 174 * @throws IllegalArgumentException if p < 0 or p > 1 175 */ 176 public int inverseCumulativeProbability(final double p) throws MathException { 177 // handle extreme values explicitly 178 if (p == 0) { 179 return -1; 180 } 181 if (p == 1) { 182 return Integer.MAX_VALUE; 183 } 184 185 // use default bisection impl 186 return super.inverseCumulativeProbability(p); 187 } 188 }