NumPy arange: How to Create Arrays of Numbers in Python

By Dr. Zubair Khalid, DVM, MS, PhD ·

NumPy arange: How to Create Arrays of Numbers in Python

numpy.arange returns an array of evenly spaced values inside a half-open interval. You give it a start, a stop and a step, and it generates numbers from start up to but not including stop. It is the array-building workhorse behind loops, plotting grids, index ranges and time-like sequences in data analysis code.

Quick Answer

  • np.arange(stop) counts from 0 up to stop, excluding stop, with a step of 1.
  • np.arange(start, stop) counts from start up to stop, excluding stop, with a step of 1.
  • np.arange(start, stop, step) spaces values by step and still excludes stop [1].
  • The length of the result follows $\lceil (stop - start) / step \rceil$ [1].
  • For non-integer steps, floating-point rounding can make the last element unpredictable, so numpy.linspace is usually the safer choice [1][2].

Syntax

The signature is numpy.arange([start, ] stop, [step, ] dtype=None, *, device=None, like=None) [1]. The square brackets mean those arguments are optional, not that you pass a list.

ArgumentRequired?Meaning
startNoFirst value in the interval. Defaults to 0. The interval includes this value [1].
stopYesEnd of the interval. The interval excludes this value [1].
stepNoSpacing between values. Defaults to 1.
dtypeNoOutput data type. If omitted, NumPy infers it from the inputs.
deviceNoDevice on which to place the array.
likeNoArray-like reference for creating the result.

You can call it with one, two or three positional arguments. arange(stop) generates values in the half-open interval [0, stop). arange(start, stop) generates values in [start, stop). arange(start, stop, step) generates values in [start, stop) with spacing given by step [1].

How It Works

The number of elements is decided by the step, not by a count you supply. NumPy computes the length as $\lceil (stop - start) / step \rceil$ [1]. That ceiling is what makes the endpoint exclusion work. If the interval divides evenly, you get exactly the number of steps that fit. If it does not, the ceiling rounds up and the final value lands short of stop.

For integer arguments, numpy.arange is roughly equivalent to Python's built-in range, but it returns an ndarray instead of a range object [1]. That difference matters. A Python range produces built-in integers with arbitrary size, while numpy.arange produces numpy.int32 or numpy.int64 numbers [1]. Very large values can overflow the fixed-width NumPy integer types where a Python range would keep going.

There is a second subtlety with floating-point steps. The actual step used to fill the array is dtype(start + step) - dtype(start), not the step you passed [1]. Casting and floating-point representation can shift that value slightly, so the last element may be larger than you expect or the length may be unstable [1]. When you need a non-integer step, the NumPy documentation recommends numpy.linspace instead [1][2].

numpy.linspace works differently. It takes a num argument for the number of elements and derives the step from it, and it includes the endpoint by default [2]. That gives you control over the count instead of the spacing.

Worked Example

The table below comes from running four array-construction calls in NumPy, covering integer steps, a fractional step, the single-argument form and a linspace comparison.

callstartstopstepresultlength
np.arange(0, 10, 2)0102[0, 2, 4, 6, 8]5
np.arange(1, 2, 0.25)120.25[1, 1.25, 1.5, 1.75]4
np.arange(5)051[0, 1, 2, 3, 4]5
np.linspace(0, 10, 6)010auto[0, 2, 4, 6, 8, 10]6

Walking through the steps:

  1. np.arange(0, 10, 2) sets start to 0, stop to 10 and step to 2. The values are 0, 2, 4, 6 and 8. The value 10 is excluded because the interval is half-open, so the result is [0, 2, 4, 6, 8].
  2. np.arange(1, 2, 0.25) sets start to 1, stop to 2 and step to 0.25. The values are 1, 1.25, 1.5 and 1.75. The last element is 1.75, and 2 is excluded, so the result is [1, 1.25, 1.5, 1.75].
  3. np.arange(5) uses only the stop argument. Start defaults to 0 and step defaults to 1, so the result is [0, 1, 2, 3, 4].
  4. np.linspace(0, 10, 6) asks for 6 elements between 0 and 10 with the endpoint included. The step is computed automatically, and the result is [0, 2, 4, 6, 8, 10].

The length formula confirms the counts. For the first call, $\lceil (10 - 0) / 2 \rceil = 5$. For the second, $\lceil (2 - 1) / 0.25 \rceil = 4$.

import numpy as np
a = np.arange(0, 10, 2)
b = np.arange(1, 2, 0.25)
c = np.arange(5)
d = np.linspace(0, 10, 6)
print(a)  # [0 2 4 6 8]
print(b)  # [1.   1.25 1.5  1.75]
print(c)  # [0 1 2 3 4]
print(d)  # [ 0.  2.  4.  6.  8. 10.]

Output:

[0 2 4 6 8]
[1.   1.25 1.5  1.75]
[0 1 2 3 4]
[ 0.  2.  4.  6.  8. 10.]

More Examples

Descending sequences use a negative step. np.arange(5, 0, -1) gives [5, 4, 3, 2, 1]. The stop value of 0 is excluded, so the array ends at 1.

Counting by tens is a common pattern for bin edges and axis ticks. np.arange(0, 100, 10) gives ten values from 0 to 90.

You can force an integer output type even with a fractional step. The manual shows np.arange(0, 5, 0.5, dtype=np.int_), which returns ten zeros because the internal step int(0 + 0.5) - int(0) is 0 [1]. This is rarely what you want, because the casting silently changes the spacing.

Indexing a DataFrame or array by position often uses np.arange(len(df)) to build a positional index. That is equivalent to np.arange(0, len(df), 1).

Errors and How to Fix Them

Passing a step of zero raises a ZeroDivisionError because the length formula divides by step. Use a nonzero step, or switch to numpy.linspace if you want a fixed number of points.

Passing complex numbers for start or stop is not supported. The arguments should be integer or real, not complex, and complex inputs give meaningless results such as a one-element or empty array rather than a clear error [2]. If you need complex values, numpy.linspace supports complex arguments [2].

Passing a float step and expecting an exact endpoint is not an error, but it produces surprising results. The last element may be greater than stop, or the length may differ from what you calculated by hand [1]. Switch to numpy.linspace when the endpoint matters.

Passing a step with the wrong sign gives an empty array. np.arange(0, 10, -1) returns an empty array because the sequence moves away from stop. Match the sign of the step to the direction you want.

Common Mistakes

  • Assuming stop is included. The interval is half-open, so np.arange(0, 10, 2) stops at 8. Use numpy.linspace with the endpoint included if you need the final value [2].
  • Using a float step for exact arithmetic. Floating-point representation can shift the last element or the length [1]. Prefer integer steps, or use numpy.linspace for fractional spacing [2].
  • Forgetting that the length comes from the step. There is no num argument in numpy.arange. If you want to control the count, use numpy.linspace [2].
  • Expecting Python integer behavior. numpy.arange returns fixed-width numpy.int32 or numpy.int64 values, which can overflow where a Python range would not [1].
  • Passing a zero step. This raises a ZeroDivisionError because the length formula divides by step.
  • Passing complex arguments. numpy.arange does not support complex start and stop values [2].

Limitations

numpy.arange cannot guarantee a stable length or a predictable final element when you use a non-integer step. The manual states that the length of the output might not be numerically stable, and that the actual step used internally is dtype(start + step) - dtype(start) rather than the step you passed [1]. Precision loss from casting, or from a start value much larger than the step, can produce unexpected results [1]. When any of those conditions apply, numpy.linspace is the better tool because it derives the step from a count you control [2].

The function also cannot include its endpoint, and it cannot produce complex sequences. Those are design choices, not bugs. If your analysis needs an inclusive endpoint or complex values, numpy.linspace covers both cases [2].

Frequently Asked Questions

What is the difference between numpy arange and Python range?

Both generate evenly spaced integers, and numpy.arange is roughly equivalent to range for integer arguments [1]. The difference is the return type. range returns a lazy range object of arbitrary-precision Python integers, while numpy.arange returns an ndarray of fixed-width numpy.int32 or numpy.int64 values [1]. Use numpy.arange when you need array operations, and range when you just need to iterate.

Does numpy arange include the stop value?

No. The interval is half-open, so the stop value is excluded [1]. np.arange(0, 10, 2) returns [0, 2, 4, 6, 8], not [0, 2, 4, 6, 8, 10]. If you need the endpoint included, use numpy.linspace, which includes it by default [2].

Why does np.arange with a float step give unexpected results?

Floating-point representation and type casting can shift the effective step. The manual notes that the actual step used to populate the array is dtype(start + step) - dtype(start), not the step you passed, and that precision loss can occur when start is much larger than step [1]. The result can be a different length or a final element beyond stop. Use numpy.linspace for non-integer steps [1][2].

How do I calculate the length of a numpy arange result?

Use the formula $\lceil (stop - start) / step \rceil$ [1]. For np.arange(0, 10, 2), that is $\lceil 10 / 2 \rceil = 5$. For np.arange(1, 2, 0.25), that is $\lceil 1 / 0.25 \rceil = 4$. The ceiling is what handles intervals that do not divide evenly.

When should I use numpy linspace instead of numpy arange?

Use numpy.linspace when you want the endpoint included, when you need a non-integer step, or when you want to specify the number of elements directly [2]. numpy.linspace takes a num argument and derives the step from it, and its endpoint argument defaults to True [2]. Use numpy.arange when you want integer steps and the endpoint does not matter [2].

References

  1. numpy.arange, NumPy v2.5 Manual
  2. How to create arrays with regularly-spaced values, NumPy v2.5 Manual

Further Reading

Related Articles