范围()为浮动
是否有一个range()
相当于在Python中的花车?
>>> range(0.5,5,1.5) [0, 1, 2, 3, 4] >>> range(0.5,5,0.5) Traceback (most recent call last): File "<pyshell#10>", line 1, in <module> range(0.5,5,0.5) ValueError: range() step argument must not be zero
我不知道一个内置的函数,但是写这样的函数不应该太复杂。
def frange(x, y, jump): while x < y: yield x x += jump
正如评论所说,这可能会产生不可预知的结果,如:
>>> list(frange(0, 100, 0.1))[-1] 99.9999999999986
为了得到预期的结果,你可以使用这个问题中的其他答案之一,或者作为@Tadhg提到的,你可以使用decimal.Decimal
作为jump
参数。 确保使用string而不是浮动来初始化它。
>>> import decimal >>> list(frange(0, 100, decimal.Decimal('0.1')))[-1] Decimal('99.9')
甚至:
import decimal def drange(x, y, jump): while x < y: yield float(x) x += decimal.Decimal(jump)
接着:
>>> list(drange(0, 100, '0.1'))[-1] 99.9
你可以使用:
[x / 10.0 for x in range(5, 50, 15)]
或者使用lambda / map:
map(lambda x: x/10.0, range(5, 50, 15))
我曾经使用numpy.arange
但由于浮点错误,有一些并发症控制它返回的元素的数量。 所以现在我使用linspace
,例如:
>>> import numpy >>> numpy.linspace(0, 10, num=4) array([ 0. , 3.33333333, 6.66666667, 10. ])
Pylab有frange
(实际上, matplotlib.mlab.frange
是一个包装器):
>>> import pylab as pl >>> pl.frange(0.5,5,0.5) array([ 0.5, 1. , 1.5, 2. , 2.5, 3. , 3.5, 4. , 4.5, 5. ])
热切评估(2.x range
):
[x * .5 for x in range(10)]
懒惰评估(2.x xrange
,3.x range
):
itertools.imap(lambda x: x * .5, xrange(10)) # or range(10) as appropriate
交替:
itertools.islice(itertools.imap(lambda x: x * .5, itertools.count()), 10) # without applying the `islice`, we get an infinite stream of half-integers.
使用itertools
:懒洋洋地评估浮点范围:
>>> from itertools import count, takewhile >>> def frange(start, stop, step): return takewhile(lambda x: x< stop, count(start, step)) >>> list(frange(0.5, 5, 1.5)) # [0.5, 2.0, 3.5]
没有这样的内置函数,但是您可以使用以下(Python 3代码)来完成Python允许的安全工作。
from fractions import Fraction def frange(start, stop, jump, end=False, via_str=False): """ Equivalent of Python 3 range for decimal numbers. Notice that, because of arithmetic errors, it is safest to pass the arguments as strings, so they can be interpreted to exact fractions. >>> assert Fraction('1.1') - Fraction(11, 10) == 0.0 >>> assert Fraction( 0.1 ) - Fraction(1, 10) == Fraction(1, 180143985094819840) Parameter `via_str` can be set to True to transform inputs in strings and then to fractions. When inputs are all non-periodic (in base 10), even if decimal, this method is safe as long as approximation happens beyond the decimal digits that Python uses for printing. For example, in the case of 0.1, this is the case: >>> assert str(0.1) == '0.1' >>> assert '%.50f' % 0.1 == '0.10000000000000000555111512312578270211815834045410' If you are not sure whether your decimal inputs all have this property, you are better off passing them as strings. String representations can be in integer, decimal, exponential or even fraction notation. >>> assert list(frange(1, 100.0, '0.1', end=True))[-1] == 100.0 >>> assert list(frange(1.0, '100', '1/10', end=True))[-1] == 100.0 >>> assert list(frange('1', '100.0', '.1', end=True))[-1] == 100.0 >>> assert list(frange('1.0', 100, '1e-1', end=True))[-1] == 100.0 >>> assert list(frange(1, 100.0, 0.1, end=True))[-1] != 100.0 >>> assert list(frange(1, 100.0, 0.1, end=True, via_str=True))[-1] == 100.0 """ if via_str: start = str(start) stop = str(stop) jump = str(jump) start = Fraction(start) stop = Fraction(stop) jump = Fraction(jump) while start < stop: yield float(start) start += jump if end and start == stop: yield(float(start))
你可以通过运行几个断言来validation它的全部内容:
assert Fraction('1.1') - Fraction(11, 10) == 0.0 assert Fraction( 0.1 ) - Fraction(1, 10) == Fraction(1, 180143985094819840) assert str(0.1) == '0.1' assert '%.50f' % 0.1 == '0.10000000000000000555111512312578270211815834045410' assert list(frange(1, 100.0, '0.1', end=True))[-1] == 100.0 assert list(frange(1.0, '100', '1/10', end=True))[-1] == 100.0 assert list(frange('1', '100.0', '.1', end=True))[-1] == 100.0 assert list(frange('1.0', 100, '1e-1', end=True))[-1] == 100.0 assert list(frange(1, 100.0, 0.1, end=True))[-1] != 100.0 assert list(frange(1, 100.0, 0.1, end=True, via_str=True))[-1] == 100.0 assert list(frange(2, 3, '1/6', end=True))[-1] == 3.0 assert list(frange(0, 100, '1/3', end=True))[-1] == 100.0
代码在GitHub上可用
我帮助将函数numeric_range添加到包more-itertools 。
more_itertools.numeric_range(start, stop, step)
作用类似于内置的函数范围,但可以处理浮点数,小数和分数types。
>>> from more_itertools import numeric_range >>> tuple(numeric_range(.1, 5, 1)) (0.1, 1.1, 2.1, 3.1, 4.1)
我写了一个函数返回一个双精度浮点数的范围的元组,没有超过百分之一的任何小数位。 这只是一个parsing范围值的问题,如string和分离多余的。 我使用它来显示范围从UI内select。 我希望别人觉得它有用。
def drange(start,stop,step): double_value_range = [] while start<stop: a = str(start) a.split('.')[1].split('0')[0] start = float(str(a)) double_value_range.append(start) start = start+step double_value_range_tuple = tuple(double_value_range) #print double_value_range_tuple return double_value_range_tuple
kichik提供了一个没有numpy等依赖关系的解决scheme ,但是由于浮点运算 ,它往往会出乎意料的performance。 正如我和blubberdiblub所指出的那样 ,其他因素很容易渗透到结果中。 例如naive_frange(0.0, 1.0, 0.1)
将产生0.999...
作为其最后的值,从而总共产生11个值。
这里提供了一个强大的版本:
def frange(x, y, jump=1.0): '''Range for floats.''' i = 0.0 x = float(x) # Prevent yielding integers. x0 = x epsilon = jump / 2.0 yield x # yield always first value while x + epsilon < y: i += 1.0 x = x0 + i * jump yield x
因为乘法,舍入误差不会累加。 epsilon
的使用考虑到了乘法的可能的舍入误差,尽pipe当然问题可能会在非常小的和非常大的端点上升。 现在,正如所料:
> a = list(frange(0.0, 1.0, 0.1)) > a[-1] 0.9 > len(a) 10
而有了更大的数字:
> b = list(frange(0.0, 1000000.0, 0.1)) > b[-1] 999999.9 > len(b) 10000000
代码也可以作为GitHub Gist使用 。
def Range(*argSequence): if len(argSequence) == 3: imin = argSequence[0]; imax = argSequence[1]; di = argSequence[2] i = imin; iList = [] while i <= imax: iList.append(i) i += di return iList if len(argSequence) == 2: return Range(argSequence[0], argSequence[1], 1) if len(argSequence) == 1: return Range(1, argSequence[0], 1)
请注意范围的第一个字母是大写。 Python的函数不鼓励这种命名方法。 如果你愿意的话,你可以把范围改成像drange或者frange。 “范围”function的行为就像你想要的一样。 你可以在这里查看它的手册[ http://reference.wolfram.com/language/ref/Range.html ]。
我认为有一个非常简单的答案,真正模拟范围的所有function,但浮动和整数。 在这个解决scheme中,你只是假设你的近似值是1e-7(或者你select的那个),你可以在调用函数的时候改变它。
def drange(start,stop=None,jump=1,approx=7): # Approx to 1e-7 by default ''' This function is equivalent to range but for both float and integer ''' if not stop: # If there is no y value: range(x) stop= start start= 0 valor= round(start,approx) while valor < stop: if valor==int(valor): yield int(round(valor,approx)) else: yield float(round(valor,approx)) valor += jump for i in drange(12): print(i)
是否有一个范围()相当于在Python中的花车? 否使用这个:
def f_range(start, end, step): a = range(int(start/0.01), int(end/0.01), int(step/0.01)) var = [] for item in a: var.append(item*0.01) return var