Как использовать десятичное значение шага ()? - PullRequest
623 голосов
/ 25 января 2009

Есть ли способ перейти между 0 и 1 на 0,1?

Я думал, что смогу сделать это следующим образом, но это не удалось:

for i in range(0, 1, 0.1):
    print i

Вместо этого он говорит, что аргумент шага не может быть нулем, чего я не ожидал.

Ответы [ 33 ]

763 голосов
/ 25 января 2009

Вместо того, чтобы использовать десятичный шаг напрямую, гораздо безопаснее выразить это в виде количества точек, которые вы хотите получить. В противном случае ошибка округления с плавающей точкой может привести к неверному результату.

Вы можете использовать функцию linspace из библиотеки NumPy (которая не является частью стандартной библиотеки, но ее относительно легко получить). 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])

Если вы действительно хотите использовать значение шага с плавающей точкой, вы можете, набрав 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])

Ошибка округления с плавающей точкой вызовет проблемы. Вот простой случай, когда из-за ошибки округления arange создает массив длины 4, когда он должен выдавать только 3 числа:

>>> numpy.arange(1, 1.3, 0.1)
array([1. , 1.1, 1.2, 1.3])
187 голосов
/ 25 января 2009

Python range () может делать только целые числа, а не с плавающей точкой. В вашем конкретном случае вы можете использовать вместо этого понимание списка:

[x * 0.1 for x in range(0, 10)]

(Замените вызов range на это выражение.)

В более общем случае вы можете написать пользовательскую функцию или генератор.

143 голосов
/ 25 января 2009

Опираясь на 'xrange ([start], stop [, step])' , вы можете определить генератор, который принимает и производит любой тип по вашему выбору (придерживайтесь типов, поддерживающих + и <):

>>> 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']
>>> 
31 голосов
/ 25 января 2009

Увеличьте величину i для петли, а затем уменьшите ее, когда вам это нужно.

for i * 100 in range(0, 100, 10):
    print i / 100.0

РЕДАКТИРОВАТЬ: Я честно не могу вспомнить, почему я думал, что это будет работать синтаксически

for i in range(0, 11, 1):
    print i / 10.0

Это должно иметь желаемый результат.

23 голосов
/ 18 мая 2014

scipy имеет встроенную функцию arange, которая обобщает конструктор Python range() для удовлетворения ваших требований обработки чисел с плавающей точкой.

from scipy import arange

22 голосов
/ 28 февраля 2017

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 до y, вы бы сделали

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]

(1/x при тестировании производил меньше шума при округлении).

16 голосов
/ 11 июня 2012

Аналогично функции 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)])
    elif n == 1:
        return([start])
    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]

seq(1, 1)

[1]

12 голосов
/ 25 января 2009

Боюсь, встроенная функция range () возвращает последовательность целочисленных значений, поэтому вы не можете использовать ее для выполнения десятичного шага.

Я бы сказал, просто используйте цикл while:

i = 0.0
while i <= 1.0:
    print i
    i += 0.1

Если вам интересно, Python конвертирует ваши 0,1 в 0, поэтому говорит, что аргумент не может быть нулевым.

11 голосов
/ 08 ноября 2012

Вот решение с использованием itertools :

import itertools

def seq(start, end, step):
    if step == 0:
        raise ValueError("step must not be 0")
    sample_count = int(abs(end - start) / step)
    return itertools.islice(itertools.count(start, step), sample_count)

Пример использования:

for i in seq(0, 1, 0.1):
    print(i)
9 голосов
/ 14 мая 2012
[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]

...