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)

Online Calculator