1
2
3
4
5
6
7
8
9
10
11
12
13
14
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
178 if (p == 0) {
179 return -1;
180 }
181 if (p == 1) {
182 return Integer.MAX_VALUE;
183 }
184
185
186 return super.inverseCumulativeProbability(p);
187 }
188 }