Skip to main content
v2026.11,858 entries · CC-BY 4.0
LAC HealthMedical & Research SuppliesReagents, PPE & instruments — chain-of-custody documented.Fast, traceable sourcing built for regulated research environments, from bench consumables to instrumentation.Shop lac.us CodeCASRAIlac.us

NumPy randint: Syntax, Exclusive High, Size and dtype

How numpy.random.randint works: the exclusive high value, size tuples, the platform-dependent dtype, and the modern Generator.integers replacement.

Written and maintained by CASRAI Editorial Board

Last updated

numpy.random.randint returns random integers from a discrete uniform distribution on the half-open interval [low, high): the low value can appear, the high value never does. Its signature is numpy.random.randint(low, high=None, size=None, dtype=int). The same function is also written numpy random randint in searches, and it is one of the legacy functions NumPy now steers new code away from in favour of Generator.integers.

What randint is used for in research

Researchers reach for randint whenever an analysis needs random whole numbers: drawing row indices for a bootstrap resample, assigning participants to numbered arms of a simulated trial, generating integer-valued test data, or picking random positions in an array. For sampling items from an existing list or array, numpy random choice is usually the more direct tool; randint is the right one when you want integers from a numeric range.

Two things make randint easy to misuse, and they are the focus of this guide: the upper bound is excluded, and the default integer type depends on the platform. The NumPy documentation also flags the function as part of the legacy RandomState API, so this guide shows the modern equivalent next to each example.

Install or access

NumPy’s own install page lists these routes. With pip:

pip install numpy

With conda (from the defaults or conda-forge channels):

conda create -n my-env
conda activate my-env
conda install numpy

The same page recommends working inside a virtual environment: python -m venv my-env, then activate it (source my-env/bin/activate on macOS and Linux, my-env\Scripts\activate on Windows) before running pip install numpy. Then import it:

import numpy as np

Step-by-step: generate random integers with randint

  1. Draw one integer from [0, low). If you pass a single argument, it is treated as the exclusive upper bound and the range starts at 0: np.random.randint(5) returns one Python int from 0 to 4.
  2. Set both bounds. np.random.randint(1, 7) returns an integer from 1 to 6, because high is one above the largest integer that can be drawn. This is the usual die-roll pattern.
  3. Ask for many values with size. np.random.randint(2, size=10) returns an array of ten values, each 0 or 1. A tuple gives a shape: np.random.randint(5, size=(2, 4)) returns a 2 by 4 array of integers in [0, 5). With the default size=None, a single value is returned.
  4. Use arrays for per-element ranges. low and high may be array-like and are broadcast against each other. np.random.randint(1, [3, 5, 10]) draws three values, the first from [1, 3), the second from [1, 5) and the third from [1, 10). np.random.randint([1, 5, 7], 10) varies the lower bound instead.
  5. Choose the type with dtype. The documentation’s own example combines broadcasting and a type: np.random.randint([1, 3, 5, 7], [[10], [20]], dtype=np.uint8) returns a 2 by 4 array of unsigned 8-bit integers.
  6. Make the run repeatable. The legacy functions share one global generator, seeded with np.random.seed. On NumPy 2.5.1, np.random.seed(0) followed by np.random.randint(1, 7, size=5) returned [5 6 1 4 4]. NumPy states that the legacy RandomState continues to use the MT19937 algorithm and that old seeds continue to reproduce the same results.

The modern equivalent: randint vs Generator.integers

The randint documentation says: “New code should use the integers method of a Generator instance instead.” The page does not mark the function deprecated, and the NumPy random-generation overview says there are no plans to remove the legacy functions, so existing code keeps working. The signature of the replacement is Generator.integers(low, high=None, size=None, dtype=np.int64, endpoint=False).

import numpy as np
rng = np.random.default_rng(seed=20261029)   # any large positive integer
rng.integers(1, 7, size=5)                   # same half-open range as randint(1, 7, size=5)
rng.integers(1, 6, size=5, endpoint=True)    # closed range: 1 to 6 inclusive

The mapping is direct. RandomState.randint corresponds to integers with endpoint=False, and the old random_integers (closed interval [low, high]) corresponds to integers with endpoint=True. A seeded default_rng produces the same stream every time you create it with the same seed, but the stream is different from the one np.random.seed gives, so switching APIs changes the numbers in an existing analysis. NumPy’s guidance on seeds is to use large, unique positive integers; default_rng accepts positive integers of any size. These generators are designed for statistical modelling and simulation, not for security or cryptography.

Output and how to read it

Is the high value included?

No. randint(low, high) samples from [low, high). If you want 6 to be possible, pass 7, or use rng.integers(1, 6, endpoint=True).

What type comes back?

A call with no size returns a Python int; a call with size returns an ndarray. The default dtype=int is the C long. The documentation warns that this is 32 bits on Windows and 64 bits on 64-bit Linux and macOS, and that since NumPy 2.0 the default integer elsewhere in NumPy is np.intp, so dtype=int here does not behave like int in most other NumPy functions. If your range, or later arithmetic on the results, could exceed 32-bit limits, pass an explicit type such as dtype=np.int64. Generator.integers defaults to np.int64, which removes the platform difference.

How to generate a 2D array of random integers

Pass a tuple to size: np.random.randint(0, 10, size=(3, 4)) returns a 3 by 4 array. The result is random, so your numbers will differ unless you seed.

Troubleshooting

  • ValueError: low >= high. The interval is empty. On NumPy 2.5.1, np.random.randint(5, 5) raised exactly this error. Remember that high is exclusive, so equal bounds leave nothing to draw.
  • ValueError: high is out of bounds for uint8. The requested range does not fit the chosen type. On the same version, np.random.randint(0, 300, dtype=np.uint8) raised this error. Pick a wider dtype or a smaller range.
  • Different results on another machine. Check the default integer type (see above) and whether the run is seeded. Setting dtype explicitly removes the first cause.
  • Results change between runs. Without a seed, the numbers differ on every run. Seed the generator when you need a repeatable analysis, and record the seed.

Free alternatives

Function Package Range it samples
numpy.random.randint(low, high) NumPy (legacy API) [low, high): high excluded
Generator.integers(low, high) NumPy (recommended for new code) [low, high) by default; [low, high] with endpoint=True
random.randint(a, b) Python standard library a <= N <= b: both ends included; an alias for randrange(a, b+1)
random.randrange(start, stop) Python standard library Selects from range(start, stop, step), so stop is excluded

The standard-library random.randint has the same name as the NumPy function but the opposite endpoint rule, a common source of off-by-one errors when code is moved between the two. NumPy’s functions return arrays directly, which matters for large simulations; for the wider toolkit, see numpy zeros for pre-allocating result arrays, numpy unique for counting what you drew and numpy repeat for building repeated index patterns.

FAQ

Is the high value included in numpy randint?

No. The interval is half-open, [low, high). Use endpoint=True with Generator.integers for a closed interval.

Is numpy random randint deprecated?

The documentation does not mark it deprecated. It belongs to the legacy RandomState API, and NumPy recommends that new code use Generator.integers. The overview page says there are no plans to remove the legacy functions.

How do I get an inclusive range?

Add one to high in randint, or call rng.integers(low, high, endpoint=True).

How do I generate a 2D array of random integers?

Give size a tuple, for example size=(2, 4).

How do I make randint reproducible?

Seed the legacy generator with np.random.seed(n), or create np.random.default_rng(n) and call integers on it.

Sources

Follow CASRAI

Research-administration guidance, standards updates and independent tool reviews.

Ask CASRAI · free to try

Ask about NumPy randint: Syntax, Exclusive High, Size and dtype

Ask your first 2 questions free below. Subscribers get 150 a day for $29 a month.

An AI assistant specialized in research administration. It cites the sources behind every answer, labels web answers and says when it can't answer.

Answers draw on CASRAI's guides and dictionary plus the federal and funder documents we index: Federal Register, Grants.gov, Regulations.gov and UKRI.

Works on this site and inside Claude, Cursor and the AI tools you already use.

Everything CASRAI publishes — this page, the dictionary, the guides and the news — stays free to read, with no account and no card.

Referenced across the research world

University of Cambridge logoColumbia University logoCrossref logoUniversity of Edinburgh logoHarvard University logoUniversity of Oxford logoPrinceton University logoStanford School of Medicine logoUniversity College London logoORCID logoUniversity of Cambridge logoColumbia University logoCrossref logoUniversity of Edinburgh logoHarvard University logoUniversity of Oxford logoPrinceton University logoStanford School of Medicine logoUniversity College London logoORCID logo
  • University of Cambridge logo
  • Columbia University logo
  • Crossref logo
  • University of Edinburgh logo
  • Harvard University logo
  • University of Oxford logo
  • Princeton University logo
  • Stanford School of Medicine logo
  • University College London logo
  • ORCID logo

View CASRAI adoption →