RANDINT
Overview
The RANDINT function computes values for the discrete uniform distribution, which assigns equal probability to each integer within a specified range. This distribution models scenarios where every outcome in a finite set of integers is equally likely, such as rolling a fair die, random selection from a numbered list, or simulation of equiprobable discrete events.
The discrete uniform distribution is characterized by two parameters: a lower bound low (inclusive) and an upper bound high (exclusive). Every integer k in the range \{low, low+1, \ldots, high-1\} has the same probability of occurring. This implementation uses SciPy’s randint distribution from the scipy.stats module.
The probability mass function (PMF) for the discrete uniform distribution is:
f(k) = \frac{1}{high - low}
for k \in \{low, low+1, \ldots, high-1\}, and zero otherwise. The PMF returns the probability that a random variable equals exactly the value k.
The cumulative distribution function (CDF) gives the probability that a random variable takes a value less than or equal to k:
F(k) = \frac{\lfloor k \rfloor - low + 1}{high - low}
for low \leq k < high.
Key statistical properties of the discrete uniform distribution include:
- Mean: \mu = \frac{low + high - 1}{2}
- Variance: \sigma^2 = \frac{(high - low)^2 - 1}{12}
The function supports multiple calculation modes: PMF (probability mass function), CDF (cumulative distribution function), SF (survival function, equal to 1 - CDF), ICDF (inverse CDF, also known as the percent point function), ISF (inverse survival function), and summary statistics including mean, variance, standard deviation, and median. An optional loc parameter shifts the entire distribution by a specified amount.
For more details on the underlying implementation, see the SciPy randint documentation and the SciPy GitHub repository.
This example function is provided as-is without any representation of accuracy.
Excel Usage
=RANDINT(k, low, high, randint_mode, loc)
k(float, required): Value(s) at which to evaluate the distribution. For PMF, CDF, SF modes, this is the integer value. For ICDF and ISF modes, this is the probability (0 to 1).low(int, required): Lower bound of the distribution (inclusive).high(int, required): Upper bound of the distribution (exclusive).randint_mode(str, optional, default: “pmf”): Output type for the distribution calculation.loc(float, optional, default: 0): Location parameter that shifts the distribution.
Returns (float): Distribution result (float), or error message string.
Examples
Example 1: PMF at k=5 with default parameters
Inputs:
| k | low | high |
|---|---|---|
| 5 | 1 | 10 |
Excel formula:
=RANDINT(5, 1, 10)
Expected output:
0.1111
Example 2: CDF at k=5
Inputs:
| k | low | high | randint_mode |
|---|---|---|---|
| 5 | 1 | 10 | cdf |
Excel formula:
=RANDINT(5, 1, 10, "cdf")
Expected output:
0.5556
Example 3: Survival function at k=5
Inputs:
| k | low | high | randint_mode | loc |
|---|---|---|---|---|
| 5 | 1 | 10 | sf | 0 |
Excel formula:
=RANDINT(5, 1, 10, "sf", 0)
Expected output:
0.4444
Example 4: Inverse CDF for probability 0.5
Inputs:
| k | low | high | randint_mode | loc |
|---|---|---|---|---|
| 0.5 | 1 | 10 | icdf | 0 |
Excel formula:
=RANDINT(0.5, 1, 10, "icdf", 0)
Expected output:
5
Example 5: Mean of distribution
Inputs:
| k | low | high | randint_mode |
|---|---|---|---|
| 1 | 1 | 10 | mean |
Excel formula:
=RANDINT(1, 1, 10, "mean")
Expected output:
5
Example 6: Variance of distribution
Inputs:
| k | low | high | randint_mode |
|---|---|---|---|
| 1 | 1 | 10 | var |
Excel formula:
=RANDINT(1, 1, 10, "var")
Expected output:
6.6667
Python Code
from scipy.stats import randint as scipy_randint
import math
def randint(k, low, high, randint_mode='pmf', loc=0):
"""
Compute Uniform discrete distribution values: PMF, CDF, SF, ICDF, ISF, mean, variance, std, or median.
See: https://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.randint.html
This example function is provided as-is without any representation of accuracy.
Args:
k (float): Value(s) at which to evaluate the distribution. For PMF, CDF, SF modes, this is the integer value. For ICDF and ISF modes, this is the probability (0 to 1).
low (int): Lower bound of the distribution (inclusive).
high (int): Upper bound of the distribution (exclusive).
randint_mode (str, optional): Output type for the distribution calculation. Valid options: PMF, CDF, SF, ICDF, ISF, Mean, Variance, Std Dev, Median. Default is 'pmf'.
loc (float, optional): Location parameter that shifts the distribution. Default is 0.
Returns:
float: Distribution result (float), or error message string.
"""
# Validate randint_mode first
valid_modes = {"pmf", "cdf", "sf", "icdf", "isf", "mean", "var", "std", "median"}
if not isinstance(randint_mode, str) or randint_mode not in valid_modes:
return "Invalid input: randint_mode must be one of 'pmf', 'cdf', 'sf', 'icdf', 'isf', 'mean', 'var', 'std', or 'median'."
# Validate low and high
try:
low_val = int(low)
high_val = int(high)
if low_val >= high_val:
return "Invalid input: low must be less than high."
except (TypeError, ValueError):
return "Invalid input: low and high must be integers."
# Validate loc
try:
loc_val = float(loc)
except (TypeError, ValueError):
return "Invalid input: loc must be a number."
# Helper to process k value
def process_k(val):
try:
return float(val)
except (TypeError, ValueError):
return None
# Handle mean/var/std/median modes (k parameter is ignored)
if randint_mode == "mean":
try:
return float(scipy_randint.mean(low_val, high_val, loc=loc_val))
except Exception as e:
return f"Error computing mean: {str(e)}"
if randint_mode == "var":
try:
return float(scipy_randint.var(low_val, high_val, loc=loc_val))
except Exception as e:
return f"Error computing variance: {str(e)}"
if randint_mode == "std":
try:
return float(scipy_randint.std(low_val, high_val, loc=loc_val))
except Exception as e:
return f"Error computing standard deviation: {str(e)}"
if randint_mode == "median":
try:
return float(scipy_randint.median(low_val, high_val, loc=loc_val))
except Exception as e:
return f"Error computing median: {str(e)}"
# PMF, CDF, SF, ICDF, ISF modes
def compute(val):
kval = process_k(val)
if kval is None:
return "Invalid input: k must be a number."
# Validate probability range for icdf/isf
if randint_mode in ["icdf", "isf"]:
if kval < 0 or kval > 1:
return "Invalid input: probability must be between 0 and 1 for icdf/isf."
try:
if randint_mode == "pmf":
result = scipy_randint.pmf(kval, low_val, high_val, loc=loc_val)
elif randint_mode == "cdf":
result = scipy_randint.cdf(kval, low_val, high_val, loc=loc_val)
elif randint_mode == "sf":
result = scipy_randint.sf(kval, low_val, high_val, loc=loc_val)
elif randint_mode == "icdf":
result = scipy_randint.ppf(kval, low_val, high_val, loc=loc_val)
elif randint_mode == "isf":
result = scipy_randint.isf(kval, low_val, high_val, loc=loc_val)
# Handle NaN/inf
if math.isnan(result):
return "Result is NaN (not a number)."
if math.isinf(result):
return "Result is infinite."
return float(result)
except Exception as e:
return f"Error in {randint_mode} calculation: {str(e)}"
# Handle 2D list or scalar input
if isinstance(k, list):
# Validate 2D list structure
if not all(isinstance(row, list) for row in k):
return "Invalid input: k must be a scalar or 2D list."
result = []
for row in k:
result_row = []
for val in row:
out = compute(val)
if isinstance(out, str):
return out
result_row.append(out)
result.append(result_row)
return result
else:
return compute(k)