5

I came across an example in the numpy docs where there is an example with a complex step size inside a slice (see the 2nd example).

From experiments, I can see what it is doing; it is similar to np.linspace.

In [42]: np.r_[-1:1:1j]
Out[42]: array([-1.])

In [43]: np.r_[-1:1:2j]
Out[43]: array([-1.,  1.])

In [44]: np.r_[-1:1:3j]
Out[44]: array([-1.,  0.,  1.])

In [45]: np.r_[-1:1:4j]
Out[45]: array([-1.        , -0.33333333,  0.33333333,  1.        ])

In [46]: np.r_[-1:1:5j]
Out[46]: array([-1. , -0.5,  0. ,  0.5,  1. ])

In [47]: np.r_[-1:1:6j]
Out[47]: array([-1. , -0.6, -0.2,  0.2,  0.6,  1. ])

In [48]: np.all(np.r_[-1:1:6j] == np.linspace(-1, 1, 6))
Out[48]: True

But I can't understand why this is expected. If we consider mathematically, adding a complex number should not change the real part of a number, only it's magnitude, which would only grow with every step!

I tried looking at the indexing docs: in the user guide, as well as the API docs; neither mention complex step sizes in slices.

Any explanation is greatly appreciated.

EDIT: I didn't read the docs thoroughly, as pointed out by the accepted answer, the behaviour is as described in the docs.

suvayu
  • 4,271
  • 2
  • 29
  • 35
  • You write "From experiments, I can see what it is doing ... ", which suggests that what it is doing is undocumented -- but the documentation that you link to explicitly describes the behavior that you mention. You are correct that the documentation doesn't say *why* it works that way. Throwing an error would make more sense (in my opinion). – John Coleman Aug 02 '21 at 11:41
  • @JohnColeman Well, if the example is present in the docs, then I would not consider it an error, undocumented yes, but intended behaviour. – suvayu Aug 02 '21 at 11:45
  • While it is intended behavior, it seems mystifying. Sort of like "`sin(string)` makes no sense, so we will interpret it as `cos(len(string))`". I suspect that there is a motivating use-case, but I have no idea what it would be. – John Coleman Aug 02 '21 at 11:51
  • @JohnColeman agreed there, apparently it's documented and I missed it. If I wanted something like this, I would probably use `np.linspace` instead to be explicit. – suvayu Aug 02 '21 at 12:04

1 Answers1

3

In the reference you've provided it says:

"However, if step is an imaginary number (i.e. 100j) then its integer portion is interpreted as a number-of-points desired and the start and stop are inclusive. In other words start:stop:stepj is interpreted as np.linspace(start, stop, step, endpoint=1) inside of the brackets. After expansion of slice notation, all comma separated sequences are concatenated together."

So when you use the imaginary slice index - you include the last point in the array, as is explained in the numpy.linspace reference here.

So in your examples - the 1 is included in all of your examples, as it is the stop item.

If we were to change the stop to 10, for example, we'd get:

in: np.r_[-10:10:6j]
out: array([-10.,  -6.,  -2.,   2.,   6.,  10.])

Cheers.

Michael
  • 2,167
  • 5
  • 23
  • 38
  • Damn, not sure how I missed this. I was searching for "complex" instead of "imaginary". Thanks! – suvayu Aug 02 '21 at 11:47