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 }