如何使用小数点范围()的步骤值?
有没有办法在0.1和0.1之间步进?
我想我可以像下面那样做,但是失败了:
for i in range(0, 1, 0.1): print i
相反,它说,这个步骤参数不能为零,这是我没有想到的。
你也可以使用NumPy库(这不是标准库的一部分,但相对容易获得),它具有arange
函数:
>>> import numpy as np >>> np.arange(0.0, 1.0, 0.1) array([ 0. , 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9])
还有linspace
函数可以让你控制在端点发生的事情(当事物不总是分成正确的“片”数时,对于浮点数是非平凡的):
>>> np.linspace(0,1,11) array([ 0. , 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1. ]) >>> np.linspace(0,1,10,endpoint=False) array([ 0. , 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9])
build立在xrange([start],stop [,step])上 ,你可以定义一个接受和产生你select的types的发生器(坚持支持+
和<
types):
>>> def drange(start, stop, step): ... r = start ... while r < stop: ... yield r ... r += step ... >>> i0=drange(0.0, 1.0, 0.1) >>> ["%g" % x for x in i0] ['0', '0.1', '0.2', '0.3', '0.4', '0.5', '0.6', '0.7', '0.8', '0.9', '1'] >>>
Python的范围()只能做整数,而不是浮点数。 在你的具体情况下,你可以使用列表理解来代替:
[x * 0.1 for x in range(0, 10)]
(使用该expression式将调用replace为范围。)
对于更一般的情况,您可能需要编写自定义函数或生成器。
增加循环的i
的幅度,然后在需要时减小它。
for i * 100 in range(0, 100, 10): print i / 100.0
编辑:我真的不记得为什么我认为这会工作在语法上
for i in range(0, 11, 1): print i / 10.0
这应该有所需的输出。
scipy
有一个内置的函数arange
,它概括了Python的range()
构造函数,以满足您对float处理的需求。
from scipy import arange
与R的 seq
函数类似,在给定正确的步长值的情况下,这个函数以任何顺序返回一个序列。 最后一个值等于停止值。
def seq(start, stop, step=1): n = int(round((stop - start)/float(step))) if n > 1: return([start + step*i for i in range(n+1)]) else: return([])
结果
seq(1, 5, 0.5)
[1.0,1.5,2.0,2.5,3.0,3.5,4.0,4.5,5.0]
seq(10, 0, -1)
[10,9,8,7,6,5,4,3,2,1,0]
seq(10, 0, -2)
[10,8,6,4,2,0]
我想,NumPy有点矫枉过正。
[p/10 for p in range(0, 10)] [0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9]
一般来说,你可以做一个1/x
的步骤
x=100 y=2 [p/x for p in range(0, int(x*y))] [0.0, 0.01, 0.02, 0.03, ..., 1.97, 1.98, 1.99]
(当我testing时, 1/x
产生较小的舍入噪音)。
import numpy as np for i in np.arange(0, 1, 0.1): print i
范围()内置函数返回一个整数值的序列,恐怕,所以你不能用它做一个小数步。
我会说只是使用一个while循环:
i = 0.0 while i <= 1.0: print i i += 0.1
如果你好奇,Python会将你的0.1转换为0,这就是为什么它告诉你参数不能为零。
[x * 0.1 for x in range(0, 10)]
在Python 2.7x中给你的结果是:
[0.0,0.1,0.2,0.30000000000000004,0.4,0.5,0.6000000000000001,0.7000000000000001,0.8,0.9]
但是如果你使用:
[ round(x * 0.1, 1) for x in range(0, 10)]
给你所需的:
[0.0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9]
这是一个使用itertools的解决scheme:
import itertools def seq(start, end, step): assert(step != 0) sample_count = abs(end - start) / step return itertools.islice(itertools.count(start, step), sample_count)
用法示例:
for i in seq(0, 1, 0.1): print i
输出:
0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9
如果你经常这样做,你可能想要保存生成的列表r
r=map(lambda x: x/10.0,range(0,10)) for i in r: print i
我的版本使用原始范围函数为转换创build乘法指数。 这允许原始范围函数使用相同的语法。 我做了两个版本,一个使用float,一个使用Decimal,因为我发现在某些情况下,我想避免浮点algorithm引入的舍入漂移。
它与range / xrange中的空集结果一致。
只将一个数字值传递给任一函数会将标准范围输出返回到input参数的整数上限值(所以如果给了它5.5,它将返回范围(6))。
编辑:下面的代码现在可以作为包在pypi: Franges
## frange.py from math import ceil # find best range function available to version (2.7.x / 3.xx) try: _xrange = xrange except NameError: _xrange = range def frange(start, stop = None, step = 1): """frange generates a set of floating point values over the range [start, stop) with step size step frange([start,] stop [, step ])""" if stop is None: for x in _xrange(int(ceil(start))): yield x else: # create a generator expression for the index values indices = (i for i in _xrange(0, int((stop-start)/step))) # yield results for i in indices: yield start + step*i ## drange.py import decimal from math import ceil # find best range function available to version (2.7.x / 3.xx) try: _xrange = xrange except NameError: _xrange = range def drange(start, stop = None, step = 1, precision = None): """drange generates a set of Decimal values over the range [start, stop) with step size step drange([start,] stop, [step [,precision]])""" if stop is None: for x in _xrange(int(ceil(start))): yield x else: # find precision if precision is not None: decimal.getcontext().prec = precision # convert values to decimals start = decimal.Decimal(start) stop = decimal.Decimal(stop) step = decimal.Decimal(step) # create a generator expression for the index values indices = ( i for i in _xrange( 0, ((stop-start)/step).to_integral_value() ) ) # yield results for i in indices: yield float(start + step*i) ## testranges.py import frange import drange list(frange.frange(0, 2, 0.5)) # [0.0, 0.5, 1.0, 1.5] list(drange.drange(0, 2, 0.5, precision = 6)) # [0.0, 0.5, 1.0, 1.5] list(frange.frange(3)) # [0, 1, 2] list(frange.frange(3.5)) # [0, 1, 2, 3] list(frange.frange(0,10, -1)) # []
这是我的解决scheme,以浮动步骤来获取范围。
使用这个函数不需要导入numpy,也不需要安装。
我很确定它可以改进和优化。 随意做到这一点,并张贴在这里。
from __future__ import division from math import log def xfrange(start, stop, step): old_start = start #backup this value digits = int(round(log(10000, 10)))+1 #get number of digits magnitude = 10**digits stop = int(magnitude * stop) #convert from step = int(magnitude * step) #0.1 to 10 (eg) if start == 0: start = 10**(digits-1) else: start = 10**(digits)*start data = [] #create array #calc number of iterations end_loop = int((stop-start)//step) if old_start == 0: end_loop += 1 acc = start for i in xrange(0, end_loop): data.append(acc/magnitude) acc += step return data print xfrange(1, 2.1, 0.1) print xfrange(0, 1.1, 0.1) print xfrange(-1, 0.1, 0.1)
输出是:
[1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0] [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.1] [-1.0, -0.9, -0.8, -0.7, -0.6, -0.5, -0.4, -0.3, -0.2, -0.1, 0.0]
你可以使用这个function:
def frange(start,end,step): return map(lambda x: x*step, range(int(start*1./step),int(end*1./step)))
为了完整的精品,function解决scheme:
def frange(a,b,s): return [] if s > 0 and a > b or s < 0 and a < b or s==0 else [a]+frange(a+s,b,s)
我的答案类似于其他人使用map(),而不需要NumPy,也没有使用lambda(尽pipe你可以)。 要获取从0.0到t_max的float值的列表,请按照dt的步骤:
def xdt(n): return dt*float(n) tlist = map(xdt, range(int(t_max/dt)+1))
添加自动更正的步骤不正确的login的可能性:
def frange(start,step,stop): step *= 2*((stop>start)^(step<0))-1 return [start+i*step for i in range(int((stop-start)/step))]
我的解决scheme
def seq(start, stop, step=1, digit=0): x = float(start) v = [] while x <= stop: v.append(round(x,digit)) x += step return v
避免舍入问题的诀窍是使用一个单独的数字来移动范围,即从开始前的一半 开始 。
# floating point range def frange(a, b, stp=1.0): i = a+stp/2.0 while i<b: yield a a += stp i += stp
或者,可以使用numpy.arange
。
它可以使用Numpy库来完成。 arange()函数允许float中的步骤。 但是,为了方便起见,它会返回一个可以使用tolist()转换为列表的numpy数组。
for i in np.arange(0, 1, 0.1).tolist(): print i
最佳解决scheme: 没有舍入错误
_________________________________________________________________________________
>>> step = .1 >>> N = 10 # number of data points >>> [ x / pow(step, -1) for x in range(0, N + 1) ] [0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0]
_________________________________________________________________________________
或者,对于设定的范围而不是设定的数据点(例如连续function),请使用:
>>> step = .1 >>> rnge = 1 # NOTE range = 1, ie span of data points >>> N = int(rnge / step >>> [ x / pow(step,-1) for x in range(0, N + 1) ] [0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0]
要实现一个函数:用f( x / pow(step, -1) )
replacex / pow(step, -1)
f( x / pow(step, -1) )
,并定义f
。
例如:
>>> import math >>> def f(x): return math.sin(x) >>> step = .1 >>> rnge = 1 # NOTE range = 1, ie span of data points >>> N = int(rnge / step) >>> [ f( x / pow(step,-1) ) for x in range(0, N + 1) ] [0.0, 0.09983341664682815, 0.19866933079506122, 0.29552020666133955, 0.3894183423086505, 0.479425538604203, 0.5646424733950354, 0.644217687237691, 0.7173560908995228, 0.7833269096274834, 0.8414709848078965]
这是我的解决scheme,与float_range(-1,0,0.01)正常工作,并没有浮点表示错误。 这不是很快,但工作正常:
from decimal import Decimal def get_multiplier(_from, _to, step): digits = [] for number in [_from, _to, step]: pre = Decimal(str(number)) % 1 digit = len(str(pre)) - 2 digits.append(digit) max_digits = max(digits) return float(10 ** (max_digits)) def float_range(_from, _to, step, include=False): """Generates a range list of floating point values over the Range [start, stop] with step size step include=True - allows to include right value to if possible !! Works fine with floating point representation !! """ mult = get_multiplier(_from, _to, step) # print mult int_from = int(round(_from * mult)) int_to = int(round(_to * mult)) int_step = int(round(step * mult)) # print int_from,int_to,int_step if include: result = range(int_from, int_to + int_step, int_step) result = [r for r in result if r <= int_to] else: result = range(int_from, int_to, int_step) # print result float_result = [r / mult for r in result] return float_result print float_range(-1, 0, 0.01,include=False) assert float_range(1.01, 2.06, 5.05 % 1, True) ==\ [1.01, 1.06, 1.11, 1.16, 1.21, 1.26, 1.31, 1.36, 1.41, 1.46, 1.51, 1.56, 1.61, 1.66, 1.71, 1.76, 1.81, 1.86, 1.91, 1.96, 2.01, 2.06] assert float_range(1.01, 2.06, 5.05 % 1, False)==\ [1.01, 1.06, 1.11, 1.16, 1.21, 1.26, 1.31, 1.36, 1.41, 1.46, 1.51, 1.56, 1.61, 1.66, 1.71, 1.76, 1.81, 1.86, 1.91, 1.96, 2.01]
我只是一个初学者,但是在模拟一些计算时,我遇到了同样的问题。 这是我试图解决这个问题,这似乎是与十进制的步骤。
我也很懒,所以我发现很难编写我自己的范围函数。
基本上我所做的是将我的xrange(0.0, 1.0, 0.01)
xrange(0, 100, 1)
xrange(0.0, 1.0, 0.01)
更改为xrange(0, 100, 1)
并在循环内用100.0
除。 我也担心,如果有四舍五入的错误。 所以我决定testing一下,是否有。 现在我听说,如果例如0.01
从一个计算不完全是浮动0.01
比较他们应该返回假(如果我错了,请让我知道)。
所以我决定通过一个简短的testing来testing我的解决scheme是否适用于我的范围:
for d100 in xrange(0, 100, 1): d = d100 / 100.0 fl = float("0.00"[:4 - len(str(d100))] + str(d100)) print d, "=", fl , d == fl
并且每个都打印为True。
现在,如果我弄错了,请告诉我。
这一个class轮不会混乱你的代码。 step参数的符号很重要。
def frange(start, stop, step): return [x*step+start for x in range(0,round(abs((stop-start)/step)+0.5001), int((stop-start)/step<0)*-2+1)]
格兰奇(开始,停止,精确)
def frange(a,b,i): p = 10**i sr = a*p er = (b*p) + 1 p = float(p) return map(lambda x: x/p, xrange(sr,er)) In >frange(-1,1,1) Out>[-1.0, -0.9, -0.8, -0.7, -0.6, -0.5, -0.4, -0.3, -0.2, -0.1, 0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0]
请阅读这篇文章 。 如果你不想使用第三方库,这是一个很好的select。
def frange(start, stop, step=1.0): ''' "range()" like function which accept float type''' i = start while i < stop: yield i i += step # Generate one element at a time. # Preferred when you don't need all generated elements at the same time. # This will save memory. for i in frange(1.0, 2.0, 0.5): print i # Use generated element. # Generate all elements at once. # Preferred when generated list ought to be small. print list(frange(1.0, 10.0, 0.5))
输出:
1.0 1.5 [1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0, 5.5, 6.0, 6.5, 7.0, 7.5, 8.0, 8.5, 9.0, 9.5]