python - proyectos - mpu6050 mercadolibre
Rango con paso de tipo float (8)
Esta pregunta ya tiene una respuesta aquí:
- ¿Cómo utilizar un valor de paso de rango decimal ()? 31 respuestas
La documentación básicamente dice que el range
debe comportarse exactamente como esta implementación (para un step
positivo):
def range(start, stop, step):
x = start
while True:
if x >= stop: return
yield x
x += step
También dice que sus argumentos deben ser enteros. ¿Porqué es eso? ¿No es esa definición también perfectamente válida si el paso es un flotador?
En mi caso, soy esp. necesita una función de range
que acepte un tipo flotante como argumento de step
. ¿Hay alguna en Python o necesito implementar la mía?
Más específico: ¿Cómo podría traducir este código C directamente a Python de una manera agradable (es decir, no solo hacerlo a través de un -loop manualmente):
for(float x = 0; x < 10; x += 0.5f) { /* ... */ }
Aquí hay un caso especial que podría ser lo suficientemente bueno:
[ (1.0/divStep)*x for x in range(start*divStep, stop*divStep)]
En tu caso esto sería:
#for(float x = 0; x < 10; x += 0.5f) { /* ... */ } ==>
start = 0
stop = 10
divstep = 1/.5 = 2 #This needs to be int, thats why I said ''special case''
y entonces:
>>> [ .5*x for x in range(0*2, 10*2)]
[0.0, 0.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]
Cuando sumas números de punto flotante juntos, a menudo hay un poco de error. ¿Devolvería un range(0.0, 2.2, 1.1)
[0.0, 1.1]
o [0.0, 1.1, 2.199999999]
? No hay manera de estar seguro sin un análisis riguroso.
El código que publicó es una solución alternativa OK si realmente lo necesita. Sólo tenga en cuenta las posibles deficiencias.
El problema con el punto flotante es que puede que no obtenga la misma cantidad de elementos que esperaba, debido a la inexactitud. Esto puede ser un problema real si estás jugando con polinomios donde el número exacto de elementos es bastante importante.
Lo que realmente quieres es una progresión aritmética; El siguiente código funcionará muy felizmente para int
, float
y complex
... y cadenas, y listas ...
def arithmetic_progression(start, step, length):
for i in xrange(length):
yield start + i * step
Tenga en cuenta que este código ofrece mayores posibilidades de que su último valor esté dentro del valor esperado de un toro que cualquier otra alternativa que mantenga un total acumulado.
>>> 10000 * 0.0001, sum(0.0001 for i in xrange(10000))
(1.0, 0.9999999999999062)
>>> 10000 * (1/3.), sum(1/3. for i in xrange(10000))
(3333.333333333333, 3333.3333333337314)
Corrección: aquí hay un gadget total competitivo :
def kahan_range(start, stop, step):
assert step > 0.0
total = start
compo = 0.0
while total < stop:
yield total
y = step - compo
temp = total + y
compo = (temp - total) - y
total = temp
>>> list(kahan_range(0, 1, 0.0001))[-1]
0.9999
>>> list(kahan_range(0, 3333.3334, 1/3.))[-1]
3333.333333333333
>>>
Esto es lo que yo usaría:
numbers = [float(x)/10 for x in range(10)]
más bien que:
numbers = [x*0.1 for x in range(10)]
that would return :
[0.0, 0.1, 0.2, 0.30000000000000004, 0.4, 0.5, 0.6000000000000001, 0.7000000000000001, 0.8, 0.9]
Espero eso ayude.
Para poder usar números decimales en una expresión de rango, una buena manera de hacerlo es la siguiente: [x * 0.1 para x en rango (0, 10)]
Podrías usar numpy.arange
.
EDITAR: Los documentos prefieren numpy.linspace
. Gracias @Droogans por darse cuenta =)
Probablemente porque no puedes tener parte de un iterable. Además, los floats
son imprecisos.
Una explicación podría ser cuestiones de redondeo de punto flotante. Por ejemplo, si pudieras llamar
range(0, 0.4, 0.1)
se podría esperar una salida de
[0, 0.1, 0.2, 0.3]
pero de hecho obtienes algo como
[0, 0.1, 0.2000000001, 0.3000000001]
Debido a problemas de redondeo. Y dado que el rango se usa a menudo para generar índices de algún tipo, son solo números enteros.
Aún así, si quieres un generador de rango para flotadores, simplemente puedes rodar el tuyo.
def xfrange(start, stop, step):
i = 0
while start + i * step < stop:
yield start + i * step
i += 1