如何确保“范围”包括零?

How to make sure that `range` includes zero?

我想要最优雅的方法来获得 -100 到 100 之间的数字 n 的倍数,其中 100 只是代表另一个长公式。 range(-100, 100, n) 当 n 为 30 时跳过 0。

n=30
想要:-90、-60、-30、0、30、60、90
range(-100, 100, n) 产量 -100、-70、-40、-10、20、50、80

目前,我正在使用

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

如您所见,这是非常难看的代码,我不喜欢这样。

我只是想要一种更优雅的方式来做到这一点(并且最好不要让一行的长度超过 80 个字符)

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

整数的简单解决方案(range):

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]

使用 numpy(np.arange 基础)用于浮点数:

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]

用一套怎么样?

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

我们可以证明所有经过0nx < 0都满足下面的公式:

y = n * x

其中 x - 一些负整数。 如果我们希望它不小于-100那么我们可以设置

x = ceil(-100 / n) * n

最后我们可以证明 ceil(-100 / n) = -floor(100 / n) 是 Python 中的 -(100 // n)(注意 - 由于 operators precedence 而在括号外)。

所以 range 通过 0 步骤 nstart 不小于 -100stop 不大于 100 我们有

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

示例:

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