mightbesimon
mightbesimon

Reputation: 479

How to make sure that `range` includes zero?

I want the most elegant way to get multiples of a number n in between -100 and 100, where 100 just represents another long formula. range(-100, 100, n) skips over 0 when n is say 30.

n=30
want: -90, -60, -30, 0, 30, 60, 90
range(-100, 100, n) yields -100, -70, -40, -10, 20, 50, 80

currently, I'm using

temp = 100//n
intervals = [i*n for i in range(-temp, temp)]
plt.gca().set_xticks(intervals, minor=True)

as you can see this is very ugly code and I don't like this.

I just want a more elegant way to do this (and preferable doesn't make the line more than 80 characters long)

plt.gca().set_xticks(something, minor=True)

Upvotes: 0

Views: 699

Answers (3)

Azat Ibrakov
Azat Ibrakov

Reputation: 10990

We can prove that all x < 0 that go through 0 with step n satisfy following formula:

y = n * x

where x - some negative whole number. If we want it to be not lesser than -100 then we can set

x = ceil(-100 / n) * n

finally we can show that ceil(-100 / n) = -floor(100 / n) which is -(100 // n) in Python (note - going outside parentheses due to operators precedence).

So for range going through 0 with step n with start not lesser than -100 and stop not greater than 100 we have

range(-(100 // n) * n, 100, n)

example:

>>> n=30
>>> list(range(-(100 // n) * n, 100, n))
[-90, -60, -30, 0, 30, 60, 90]

Upvotes: 4

shrewmouse
shrewmouse

Reputation: 6040

How about using a set?

>>> sorted(set(range(0,-100,-30)[::-1] + list(range(0,100, 30))))
[-90, -60, -30, 0, 30, 60, 90]

Upvotes: 1

Stanislav Ivanov
Stanislav Ivanov

Reputation: 1974

Simple solution (range based) for integers:

def mk_zero_centred_range(xmin, xmax, xstep):
    assert xmin <= 0 and xmax > 0 and xstep > 0
    return [-x for x in range(0, -xmin, xstep)[1:][::-1]] + list(range(0, xmax, xstep))

print(mk_zero_centred_range(-5, 5, 1)) #[-4, -3, -2, -1, 0, 1, 2, 3, 4]
print(mk_zero_centred_range(-7, 9, 2)) #[-6, -4, -2, 0, 2, 4, 6, 8]

With numpy (np.arange based) for floats:

import numpy as np

def mk_zero_centred_arange(xmin, xmax, xstep):
    assert xmin <= 0 and xmax > 0 and xstep > 0
    return np.r_[-np.arange(0, -xmin, xstep)[1:][::-1],np.arange(0, xmax, xstep)]

print(mk_zero_centred_arange(-3, 5, 0.4))
# [-2.8 -2.4 -2. -1.6 -1.2 -0.8 -0.4  0. 0.4 0.8 1.2 1.6 2. 2.4 2.8 3.2 3.6 4. 4.4 4.8]
print(mk_zero_centred_arange(0, 5, 0.3))
# [0.  0.3 0.6 0.9 1.2 1.5 1.8 2.1 2.4 2.7 3.  3.3 3.6 3.9 4.2 4.5 4.8]

Upvotes: 1

Related Questions