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
018 package org.apache.commons.math3.distribution;
019
020 import org.apache.commons.math3.exception.NumberIsTooLargeException;
021 import org.apache.commons.math3.exception.util.LocalizedFormats;
022 import org.apache.commons.math3.random.RandomGenerator;
023 import org.apache.commons.math3.random.Well19937c;
024 import org.apache.commons.math3.util.FastMath;
025
026 /**
027 * Implementation of the uniform integer distribution.
028 *
029 * @see <a href="http://en.wikipedia.org/wiki/Uniform_distribution_(discrete)"
030 * >Uniform distribution (discrete), at Wikipedia</a>
031 *
032 * @version $Id: UniformIntegerDistribution.java 1416643 2012-12-03 19:37:14Z tn $
033 * @since 3.0
034 */
035 public class UniformIntegerDistribution extends AbstractIntegerDistribution {
036 /** Serializable version identifier. */
037 private static final long serialVersionUID = 20120109L;
038 /** Lower bound (inclusive) of this distribution. */
039 private final int lower;
040 /** Upper bound (inclusive) of this distribution. */
041 private final int upper;
042
043 /**
044 * Creates a new uniform integer distribution using the given lower and
045 * upper bounds (both inclusive).
046 *
047 * @param lower Lower bound (inclusive) of this distribution.
048 * @param upper Upper bound (inclusive) of this distribution.
049 * @throws NumberIsTooLargeException if {@code lower >= upper}.
050 */
051 public UniformIntegerDistribution(int lower, int upper)
052 throws NumberIsTooLargeException {
053 this(new Well19937c(), lower, upper);
054 }
055
056 /**
057 * Creates a new uniform integer distribution using the given lower and
058 * upper bounds (both inclusive).
059 *
060 * @param rng Random number generator.
061 * @param lower Lower bound (inclusive) of this distribution.
062 * @param upper Upper bound (inclusive) of this distribution.
063 * @throws NumberIsTooLargeException if {@code lower >= upper}.
064 * @since 3.1
065 */
066 public UniformIntegerDistribution(RandomGenerator rng,
067 int lower,
068 int upper)
069 throws NumberIsTooLargeException {
070 super(rng);
071
072 if (lower >= upper) {
073 throw new NumberIsTooLargeException(
074 LocalizedFormats.LOWER_BOUND_NOT_BELOW_UPPER_BOUND,
075 lower, upper, false);
076 }
077 this.lower = lower;
078 this.upper = upper;
079 }
080
081 /** {@inheritDoc} */
082 public double probability(int x) {
083 if (x < lower || x > upper) {
084 return 0;
085 }
086 return 1.0 / (upper - lower + 1);
087 }
088
089 /** {@inheritDoc} */
090 public double cumulativeProbability(int x) {
091 if (x < lower) {
092 return 0;
093 }
094 if (x > upper) {
095 return 1;
096 }
097 return (x - lower + 1.0) / (upper - lower + 1.0);
098 }
099
100 /**
101 * {@inheritDoc}
102 *
103 * For lower bound {@code lower} and upper bound {@code upper}, the mean is
104 * {@code 0.5 * (lower + upper)}.
105 */
106 public double getNumericalMean() {
107 return 0.5 * (lower + upper);
108 }
109
110 /**
111 * {@inheritDoc}
112 *
113 * For lower bound {@code lower} and upper bound {@code upper}, and
114 * {@code n = upper - lower + 1}, the variance is {@code (n^2 - 1) / 12}.
115 */
116 public double getNumericalVariance() {
117 double n = upper - lower + 1;
118 return (n * n - 1) / 12.0;
119 }
120
121 /**
122 * {@inheritDoc}
123 *
124 * The lower bound of the support is equal to the lower bound parameter
125 * of the distribution.
126 *
127 * @return lower bound of the support
128 */
129 public int getSupportLowerBound() {
130 return lower;
131 }
132
133 /**
134 * {@inheritDoc}
135 *
136 * The upper bound of the support is equal to the upper bound parameter
137 * of the distribution.
138 *
139 * @return upper bound of the support
140 */
141 public int getSupportUpperBound() {
142 return upper;
143 }
144
145 /**
146 * {@inheritDoc}
147 *
148 * The support of this distribution is connected.
149 *
150 * @return {@code true}
151 */
152 public boolean isSupportConnected() {
153 return true;
154 }
155
156 /** {@inheritDoc} */
157 @Override
158 public int sample() {
159 final double r = random.nextDouble();
160 final double scaled = r * upper + (1 - r) * lower + r;
161 return (int) FastMath.floor(scaled);
162 }
163 }