Есть ли 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
range(5, 50, 5)
а затем просто делить каждое число на 10.Ответы:
Я не знаю встроенной функции, но написать такую не должно быть слишком сложно.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
аргумента. Обязательно инициализируйте его строкой, а не плавающей точкой.>>> 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
источник
>>> print list(frange(0,100,0.1))[-1]==100.0
будетFalse
frange
может работать неожиданно. Из-за проклятия арифметики с плавающей запятой , например,frange(0.0, 1.0, 0.1)
дает 11 значений, где находится последнее значение0.9999999999999999
. Практическое улучшение было бы,while x + sys.float_info.epsilon < y:
хотя даже это, вероятно, может потерпеть неудачу с большим числом .decimal.Decimal
как step вместо float.Вы можете использовать:
[x / 10.0 for x in range(5, 50, 15)]
или используйте лямбда / карту:
map(lambda x: x/10.0, range(5, 50, 15))
источник
arange(0.5, 5, 1.5)
ИМО более читабельно.list(frange(0, 1, 0.5))
, он работает нормально, и 1 исключен, но если вы попытаетесьlist(frange(0, 1, 0.1))
, последнее полученное значение будет близко к 1,0, что, вероятно, не то, что вам нужно. Представленные здесь решения не имеют этой проблемы.Раньше я использовал,
numpy.arange
но у меня были некоторые сложности с контролем количества возвращаемых элементов из-за ошибок с плавающей запятой. Итак, теперь я используюlinspace
, например:>>> import numpy >>> numpy.linspace(0, 10, num=4) array([ 0. , 3.33333333, 6.66666667, 10. ])
источник
decimal
, например:np.linspace(-.1,10,num=5050)[0]
np.linspace(-.1,10,num=5050)[0] == -.1
это правда. Простоrepr(np.float64('-0.1'))
цифра показывает больше.print(numpy.linspace(0, 3, 148)[49])
распечатывает,0.9999999999999999
когда будет идеальный результат1.0
.linspace
работает намного лучше, чемarange
, но не гарантирует минимально возможную ошибку округления.У 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.xrange
):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.
источник
(x * .5 for x in range(10))
в качестве генератора выражения для ленивых вычислений?использование
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]
источник
itertools.takewhile
. Однакоitertools.count(start, step)
страдает от накопленных ошибок с плавающей запятой. (Оцените,takewhile(lambda x: x < 100, count(0, 0.1))
например.) Я бы написалtakewhile(lambda x: x < stop, (start + i * step for i in count()))
вместо этого.Я помог добавить функцию numeric_range в пакет more-itertools .
more_itertools.numeric_range(start, stop, step)
действует как встроенный диапазон функций, но может обрабатывать типы с плавающей запятой, десятичные числа и дроби.>>> from more_itertools import numeric_range >>> tuple(numeric_range(.1, 5, 1)) (0.1, 1.1, 2.1, 3.1, 4.1)
источник
Такой встроенной функции нет, но вы можете использовать следующий код (код 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))
Вы можете проверить все это, выполнив несколько утверждений:
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
источник
Раствор без Numpy и т.д. зависимостей был предоставлен Kichik но из - за точечную арифметику с плавающей , она часто ведет себя неожиданно. Как отметили я и 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
устраняет возможную ошибку округления при умножении, даже если проблемы, конечно, могут возникнуть на очень малых и очень больших концах. Теперь, как и ожидалось:> 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 .
источник
Почему в стандартной библиотеке нет реализации диапазона с плавающей запятой?
Как ясно из всех сообщений здесь, версии с плавающей запятой не существует
range()
. Тем не менее, упущение имеет смысл, если учесть, чтоrange()
функция часто используется как генератор индекса (и, конечно, это означает средство доступа ). Итак, когда мы вызываемrange(0,40)
, мы фактически говорим, что хотим 40 значений, начиная с 0, до 40, но не включая 40 значений.Если учесть, что создание индекса зависит от количества индексов и их значений, использование реализации типа float
range()
в стандартной библиотеке имеет меньший смысл. Например, если мы вызываем функциюfrange(0, 10, 0.25)
, мы ожидаем, что будут включены как 0, так и 10, но это даст вектор с 41 значением.Таким образом,
frange()
функция, в зависимости от ее использования, всегда будет демонстрировать противоречивое интуитивное поведение; он либо имеет слишком много значений с точки зрения индексации, либо не включает число, которое должно быть возвращено с математической точки зрения.Математический пример использования
С учетом сказанного, как уже говорилось,
numpy.linspace()
генерация прекрасно выполняется с математической точки зрения:numpy.linspace(0, 10, 41) array([ 0. , 0.25, 0.5 , 0.75, 1. , 1.25, 1.5 , 1.75, 2. , 2.25, 2.5 , 2.75, 3. , 3.25, 3.5 , 3.75, 4. , 4.25, 4.5 , 4.75, 5. , 5.25, 5.5 , 5.75, 6. , 6.25, 6.5 , 6.75, 7. , 7.25, 7.5 , 7.75, 8. , 8.25, 8.5 , 8.75, 9. , 9.25, 9.5 , 9.75, 10. ])
Пример использования индексирования
Что касается индексации, я написал немного другой подход с использованием хитрой строковой магии, которая позволяет нам указывать количество десятичных знаков.
# Float range function - string formatting method def frange_S (start, stop, skip = 1.0, decimals = 2): for i in range(int(start / skip), int(stop / skip)): yield float(("%0." + str(decimals) + "f") % (i * skip))
Точно так же мы также можем использовать встроенную
round
функцию и указать количество десятичных знаков:# Float range function - rounding method def frange_R (start, stop, skip = 1.0, decimals = 2): for i in range(int(start / skip), int(stop / skip)): yield round(i * skip, ndigits = decimals)
Быстрое сравнение и производительность
Конечно, учитывая вышесказанное, эти функции имеют довольно ограниченный вариант использования. Тем не менее, вот небольшое сравнение:
def compare_methods (start, stop, skip): string_test = frange_S(start, stop, skip) round_test = frange_R(start, stop, skip) for s, r in zip(string_test, round_test): print(s, r) compare_methods(-2, 10, 1/3)
Результаты идентичны для каждого:
-2.0 -2.0 -1.67 -1.67 -1.33 -1.33 -1.0 -1.0 -0.67 -0.67 -0.33 -0.33 0.0 0.0 ... 8.0 8.0 8.33 8.33 8.67 8.67 9.0 9.0 9.33 9.33 9.67 9.67
И некоторые тайминги:
>>> import timeit >>> setup = """ ... def frange_s (start, stop, skip = 1.0, decimals = 2): ... for i in range(int(start / skip), int(stop / skip)): ... yield float(("%0." + str(decimals) + "f") % (i * skip)) ... def frange_r (start, stop, skip = 1.0, decimals = 2): ... for i in range(int(start / skip), int(stop / skip)): ... yield round(i * skip, ndigits = decimals) ... start, stop, skip = -1, 8, 1/3 ... """ >>> min(timeit.Timer('string_test = frange_s(start, stop, skip); [x for x in string_test]', setup=setup).repeat(30, 1000)) 0.024284090992296115 >>> min(timeit.Timer('round_test = frange_r(start, stop, skip); [x for x in round_test]', setup=setup).repeat(30, 1000)) 0.025324633985292166
Похоже, метод форматирования строк выигрывает в моей системе.
Ограничения
И, наконец, демонстрация сути вышеприведенного обсуждения и последнее ограничение:
# "Missing" the last value (10.0) for x in frange_R(0, 10, 0.25): print(x) 0.25 0.5 0.75 1.0 ... 9.0 9.25 9.5 9.75
Кроме того, когда
skip
параметр не делится наstop
значение, может возникнуть зияющий разрыв из-за последней проблемы:# Clearly we know that 10 - 9.43 is equal to 0.57 for x in frange_R(0, 10, 3/7): print(x) 0.0 0.43 0.86 1.29 ... 8.14 8.57 9.0 9.43
Есть способы решить эту проблему, но, в конце концов, лучшим подходом, вероятно, было бы просто использовать Numpy.
источник
Более простая версия без библиотеки
Ой, черт возьми, я добавлю простую версию без библиотеки. Не стесняйтесь улучшать его [*]:
def frange(start=0, stop=1, jump=0.1): nsteps = int((stop-start)/jump) dy = stop-start # f(i) goes from start to stop as i goes from 0 to nsteps return [start + float(i)*dy/nsteps for i in range(nsteps)]
Основная идея состоит в том, что
nsteps
это количество шагов, которые нужно пройти от начала до конца, иrange(nsteps)
всегда выдает целые числа, поэтому нет потери точности. Последний шаг - линейно отобразить [0..nsteps] на [start..stop].редактировать
Если вы, как и alancalvitti , хотите, чтобы серия имела точное рациональное представление, вы всегда можете использовать Fractions :
from fractions import Fraction def rrange(start=0, stop=1, jump=0.1): nsteps = int((stop-start)/jump) return [Fraction(i, nsteps) for i in range(nsteps)]
[*] В частности,
frange()
возвращает список, а не генератор. Но для моих нужд этого хватило.источник
frange(0,1.1,0.1)
и даже больше тех, у кого есть выбор, напримерfrange(0,1.05,0.1)
import numpy as np np.arange(0.5,5,1.5) >> [0.5, 2.0, 3.5, 5.0] # OBS you will sometimes see stuff like this happening, # so you need to decide whether that's not an issue for you, or how you are going to catch it. >> [0.50000001, 2.0, 3.5, 5.0]
Примечание 1. Из обсуждения в разделе комментариев здесь, «никогда не используйте
numpy.arange()
(сама документация numpy не рекомендует этого). Используйте numpy.linspace, как рекомендовано wim, или одно из других предложений в этом ответе»Примечание 2: я прочитал обсуждение в нескольких комментариях здесь, но, вернувшись к этому вопросу в третий раз, я считаю, что эту информацию следует разместить в более удобном для чтения месте.
источник
Как писал Кичик , это не должно быть слишком сложно. Однако этот код:
def frange(x, y, jump): while x < y: yield x x += jump
Неуместен из-за кумулятивного эффекта ошибок при работе с поплавками. Вот почему вы получаете что-то вроде:
>>>list(frange(0, 100, 0.1))[-1] 99.9999999999986
Хотя ожидаемое поведение будет:
>>>list(frange(0, 100, 0.1))[-1] 99.9
Решение 1
Кумулятивную ошибку можно просто уменьшить, используя индексную переменную. Вот пример:
from math import ceil def frange2(start, stop, step): n_items = int(ceil((stop - start) / step)) return (start + i*step for i in range(n_items))
Этот пример работает должным образом.
Решение 2
Нет вложенных функций. Только время и переменная счетчика:
def frange3(start, stop, step): res, n = start, 1 while res < stop: yield res res = start + n * step n += 1
Эта функция тоже будет работать хорошо, за исключением случаев, когда вам нужен обратный диапазон. Например:
>>>list(frange3(1, 0, -.1)) []
Решение 1 в этом случае будет работать должным образом. Чтобы эта функция работала в таких ситуациях, вы должны применить хак, подобный следующему:
from operator import gt, lt def frange3(start, stop, step): res, n = start, 0. predicate = lt if start < stop else gt while predicate(res, stop): yield res res = start + n * step n += 1
С помощью этого хака вы можете использовать эти функции с отрицательными шагами:
>>>list(frange3(1, 0, -.1)) [1, 0.9, 0.8, 0.7, 0.6, 0.5, 0.3999999999999999, 0.29999999999999993, 0.19999999999999996, 0.09999999999999998]
Решение 3
Вы можете пойти еще дальше с простой стандартной библиотекой и составить функцию диапазона для большинства числовых типов:
from itertools import count from itertools import takewhile def any_range(start, stop, step): start = type(start + step)(start) return takewhile(lambda n: n < stop, count(start, step))
Этот генератор адаптирован из книги Fluent Python (Глава 14. Итерационные объекты, итераторы и генераторы). Это не сработает с уменьшающимися диапазонами. Вы должны применить хак, как в предыдущем решении.
Вы можете использовать этот генератор, например, следующим образом:
>>>list(any_range(Fraction(2, 1), Fraction(100, 1), Fraction(1, 3)))[-1] 299/3 >>>list(any_range(Decimal('2.'), Decimal('4.'), Decimal('.3'))) [Decimal('2'), Decimal('2.3'), Decimal('2.6'), Decimal('2.9'), Decimal('3.2'), Decimal('3.5'), Decimal('3.8')]
И, конечно, вы также можете использовать его с float и int .
Быть осторожен
Если вы хотите использовать эти функции с отрицательными шагами, вы должны добавить отметку о шаге, например:
no_proceed = (start < stop and step < 0) or (start > stop and step > 0) if no_proceed: raise StopIteration
Лучше всего поднять
StopIteration
, если вы хотите имитироватьrange
саму функцию.Мимический диапазон
Если вы хотите имитировать
range
интерфейс функции, вы можете предоставить несколько проверок аргументов:def any_range2(*args): if len(args) == 1: start, stop, step = 0, args[0], 1. elif len(args) == 2: start, stop, step = args[0], args[1], 1. elif len(args) == 3: start, stop, step = args else: raise TypeError('any_range2() requires 1-3 numeric arguments') # here you can check for isinstance numbers.Real or use more specific ABC or whatever ... start = type(start + step)(start) return takewhile(lambda n: n < stop, count(start, step))
Я думаю, вы поняли. Вы можете использовать любую из этих функций (кроме самой первой), и все, что вам нужно для них, - это стандартная библиотека Python.
источник
Я написал функцию, которая возвращает кортеж из диапазона чисел с плавающей запятой двойной точности без каких-либо десятичных знаков за пределами сотых. это был просто вопрос разбора значений диапазона, таких как строки, и отделения лишнего. Я использую его для отображения диапазонов для выбора из пользовательского интерфейса. Надеюсь, кому-то это пригодится.
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
источник
Применение
# Counting up drange(0, 0.4, 0.1) [0, 0.1, 0.2, 0.30000000000000004, 0.4] # Counting down drange(0, -0.4, -0.1) [0, -0.1, -0.2, -0.30000000000000004, -0.4]
Чтобы округлить каждый шаг до N десятичных знаков
drange(0, 0.4, 0.1, round_decimal_places=4) [0, 0.1, 0.2, 0.3, 0.4] drange(0, -0.4, -0.1, round_decimal_places=4) [0, -0.1, -0.2, -0.3, -0.4]
Код
def drange(start, end, increment, round_decimal_places=None): result = [] if start < end: # Counting up, e.g. 0 to 0.4 in 0.1 increments. if increment < 0: raise Exception("Error: When counting up, increment must be positive.") while start <= end: result.append(start) start += increment if round_decimal_places is not None: start = round(start, round_decimal_places) else: # Counting down, e.g. 0 to -0.4 in -0.1 increments. if increment > 0: raise Exception("Error: When counting down, increment must be negative.") while start >= end: result.append(start) start += increment if round_decimal_places is not None: start = round(start, round_decimal_places) return result
Почему выбрали этот ответ?
np.linspace
являются случайными, они могут работать или не работать из-за трудности выбора правильного количества делений.np.linspace
действительно борется с десятичными приращениями 0,1, и порядок деления в формуле для преобразования приращения в количество разбиений может привести либо к правильному, либо к неверному коду.np.arange
, устарели.Если сомневаетесь, попробуйте четыре приведенных выше тестовых случая.
источник
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. Вы можете изменить Range на что-то вроде drange или frange, если хотите. Функция «Диапазон» ведет себя так, как вы этого хотите. Вы можете проверить это руководство здесь [ http://reference.wolfram.com/language/ref/Range.html ].
источник
Я думаю, что есть очень простой ответ, который действительно имитирует все функции диапазона, но как для чисел с плавающей точкой, так и для целых чисел. В этом решении вы просто предполагаете, что ваше приближение по умолчанию равно 1e-7 (или то, которое вы выберете), и вы можете изменить его при вызове функции.
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)
источник
Конечно, будут некоторые ошибки округления, так что это не идеально, но это то, что я обычно использую для приложений, которые не требуют высокой точности. Если вы хотите сделать это более точным, вы можете добавить дополнительный аргумент, чтобы указать, как обрабатывать ошибки округления. Возможно, передача функции округления сделает это расширяемым и позволит программисту указать, как обрабатывать ошибки округления.
arange = lambda start, stop, step: [i + step * i for i in range(int((stop - start) / step))]
Если я напишу:
arange(0, 1, 0.1)
Он выведет:
[0.0, 0.1, 0.2, 0.30000000000000004, 0.4, 0.5, 0.6000000000000001, 0.7000000000000001, 0.8, 0.9]
источник
Поговорим о том, чтобы сделать гору из кротовины. Если вы ослабите требование сделать аналог
range
функции с плавающей запятой и просто создадите список с плавающей запятой, который легко использовать вfor
цикле, кодирование будет простым и надежным.def super_range(first_value, last_value, number_steps): if not isinstance(number_steps, int): raise TypeError("The value of 'number_steps' is not an integer.") if number_steps < 1: raise ValueError("Your 'number_steps' is less than 1.") step_size = (last_value-first_value)/(number_steps-1) output_list = [] for i in range(number_steps): output_list.append(first_value + step_size*i) return output_list first = 20.0 last = -50.0 steps = 5 print(super_range(first, last, steps))
На выходе будет
[20.0, 2.5, -15.0, -32.5, -50.0]
Обратите внимание, что функция
super_range
не ограничивается поплавками. Он может обрабатывать любой тип данных , для которых операторы+
,-
,*
, и/
определены, напримерcomplex
,Decimal
иnumpy.array
:import cmath first = complex(1,2) last = complex(5,6) steps = 5 print(super_range(first, last, steps)) from decimal import * first = Decimal(20) last = Decimal(-50) steps = 5 print(super_range(first, last, steps)) import numpy as np first = np.array([[1, 2],[3, 4]]) last = np.array([[5, 6],[7, 8]]) steps = 5 print(super_range(first, last, steps))
Результат будет:
[(1+2j), (2+3j), (3+4j), (4+5j), (5+6j)] [Decimal('20.0'), Decimal('2.5'), Decimal('-15.0'), Decimal('-32.5'), Decimal('-50.0')] [array([[1., 2.],[3., 4.]]), array([[2., 3.],[4., 5.]]), array([[3., 4.],[5., 6.]]), array([[4., 5.],[6., 7.]]), array([[5., 6.],[7., 8.]])]
источник
Есть ли в Python эквивалент range () для чисел с плавающей запятой? НЕТ Используйте это:
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
источник
f_range(0.01,0.02,0.001)
... Для большинства практических целейarange
от Numpy - простое, безопасное и быстрое решение.Здесь есть несколько ответов, которые не обрабатывают простые крайние случаи, такие как отрицательный шаг, неправильный запуск, остановка и т. Д. Вот версия, которая обрабатывает многие из этих случаев правильно, давая такое же поведение, как родное
range()
:def frange(start, stop=None, step=1): if stop is None: start, stop = 0, start steps = int((stop-start)/step) for i in range(steps): yield start start += step
Обратите внимание, что это приведет к ошибке step = 0, как и native
range
. Одно отличие состоит в том, что собственный диапазон возвращает объект, который является индексируемым и обратимым, а указанный выше - нет.Вы можете поиграть с этим кодом и тестовыми примерами здесь.
источник