范围()浮动

时间:2011-09-01 07:30:04

标签: python range fractions decimal

Python中的浮点数是否等效range()

>>> 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

22 个答案:

答案 0 :(得分:91)

您可以使用:

[x / 10.0 for x in range(5, 50, 15)]

或使用lambda / map:

map(lambda x: x/10.0, range(5, 50, 15))

答案 1 :(得分:90)

我不知道内置函数,但写this之类的函数不应该太复杂。

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

答案 2 :(得分:68)

我过去常常使用numpy.arange,但由于浮点错误,控制返回的元素数会有一些复杂因素。所以现在我使用linspace,例如:

>>> import numpy
>>> numpy.linspace(0, 10, num=4)
array([  0.        ,   3.33333333,   6.66666667,  10.        ])

答案 3 :(得分:37)

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. ])

答案 4 :(得分:10)

热切评估(2.x range):

[x * .5 for x in range(10)]

Lazily评估(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.

答案 5 :(得分:8)

使用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]

答案 6 :(得分:5)

我帮助将函数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)

答案 7 :(得分:3)

k solution without numpy etc dependencies由kichik提供,但由于the floating point arithmetics,它通常会出乎意料地出现。正如meblubberdiblub所述,其他元素很容易潜入结果中。例如,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

代码也可以a GitHub Gist

答案 8 :(得分:3)

没有这样的内置函数,但您可以使用以下(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

上提供的代码

答案 9 :(得分:3)

正如 kichik 所写,这应该不太复杂。但是这段代码:

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标准库。

答案 10 :(得分:2)

为什么标准库中没有浮点范围实现?

正如此处所有帖子所明确的那样,range()没有浮点版本。也就是说,如果我们认为range()函数经常被用作索引(当然,这意味着 accessor )生成器,那么遗漏就有意义了。因此,当我们致电range(0,40)时,我们实际上说我们希望40个值从0开始,最多40个,但不包括40个本身。

当我们考虑索引生成与索引数量一样多时,在标准库中使用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)

快速比较&amp;性能

当然,鉴于上述讨论,这些功能具有相当有限的用例。尽管如此,这是一个快速比较:

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。

答案 11 :(得分:1)

更简单的无库版本

糟糕,我会折腾成一个简单的无库版本。随时进行改进[*]:

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()返回一个列表,而不是生成器。但这足以满足我的需求。

答案 12 :(得分:1)

  

这可以通过numpy.arange(开始,停止,逐步调整大小)完成

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文档本身建议不要使用它。)请按照wim的建议使用numpy.linspace,或此答案中的其他建议之一”。

注释2: 我已经在这里阅读了一些评论,但现在已经第三次回到这个问题了,我觉得这些信息应该放在更易读的位置。

答案 13 :(得分:1)

用法

# 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的答案。

如有疑问,请尝试上述四个测试案例。

答案 14 :(得分:0)

我编写了一个函数,它返回一系列双精度浮点数的元组,没有超过百分之一的小数位数。它只是解析范围值如字符串和分割多余的问题。我用它来显示范围,以便在UI中进行选择。我希望其他人觉得它很有用。

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

答案 15 :(得分:0)

这里有一些答案不能处理简单的极端情况,例如负步,错误的启动,停止等。这是正确处理许多情况的版本,其行为与本机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  

请注意,这将导致步骤= 0出错,就像本机range一样。区别之一是本机范围返回的对象是可索引和可​​逆的,而上面的对象则不是。

您可以在这里play with this code和测试用例。

答案 16 :(得分:0)

当然会有一些舍入错误,所以这不是完美的,但这是我通常用于不需要高精度的应用程序的方法。如果要使其更准确,可以添加一个额外的参数来指定如何处理舍入错误。传递舍入函数也许可以使其具有可扩展性,并允许程序员指定如何处理舍入错误。

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]

答案 17 :(得分:0)

谈论用a鼠山建造一座山。 如果放宽对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不仅限于浮点数。它可以处理定义了运算符+-*/的任何数据类型,例如complexDecimal ,和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.]])]

答案 18 :(得分:0)

尽管基于整数的范围在“所见即所得”中得到了很好的定义,但有些东西在浮点数中不容易看到,这会导致在所需范围内获得看似明确定义的行为时遇到麻烦.

可以采取两种方法:

  1. 将给定的范围分成一定数量的段:linspace 方法,当您选择一些不能很好地划分跨度的点(例如 0 到 1 7 步将给出第一步值 0.14285714285714285)

  2. 给出所需的 WYSIWIG 步长,您已经知道它应该起作用并希望它起作用。您的希望往往会因获得与您想要达到的终点不符的值而破灭。

倍数可能高于或低于您的预期:

>>> 3*.1 > .3  # 0.30000000000000004
True

>>> 3*.3 < 0.9  # 0.8999999999999999
True

您将尝试通过添加步骤的倍数而不是递增来避免累积错误,但问题总是会出现,如果您在纸上手工完成,您将无法获得预期的结果 - 使用精确的小数.但是您知道这应该是可能的,因为 Python 向您显示 0.1 而不是接近 0.1 的基本整数比率:

>>> (3*.1).as_integer_ratio()
(1351079888211149, 4503599627370496)

在作为答案提供的方法中,最好使用分数 here 以及将输入处理为字符串的选项。我有一些建议可以让它变得更好:

  1. 让它处理类似范围的默认值,这样你就可以自动从 0 开始
  2. 让它处理递减的范围
  3. 使输出看起来像您使用精确算术时所期望的

我提供了一个可以做同样事情但不使用 Fraction 对象的例程。相反,它使用 round 创建具有与使用 python 打印的数字相同的明显数字的数字,例如1 位小数表示 0.1,3 位小数表示 0.004:

def frange(start, stop, step, n=None):
    """return a WYSIWYG series of float values that mimic range behavior
    by excluding the end point and not printing extraneous digits beyond
    the precision of the input numbers (controlled by n and automatically
    detected based on the string representation of the numbers passed).

    EXAMPLES
    ========

    non-WYSIWYS simple list-comprehension

    >>> [.11 + i*.1 for i in range(3)]
    [0.11, 0.21000000000000002, 0.31]

    WYSIWYG result for increasing sequence

    >>> list(frange(0.11, .33, .1))
    [0.11, 0.21, 0.31]

    and decreasing sequences

    >>> list(frange(.345, .1, -.1))
    [0.345, 0.245, 0.145]

    To hit the end point for a sequence that is divisibe by
    the step size, make the end point a little bigger by
    adding half the step size:

    >>> dx = .2
    >>> list(frange(0, 1 + dx/2, dx))
    [0.0, 0.2, 0.4, 0.6, 0.8, 1.0]

    """
    if step == 0:
        raise ValueError('step must not be 0')
    # how many decimal places are showing?
    if n is None:
        n = max([0 if '.' not in str(i) else len(str(i).split('.')[1])
                for i in (start, stop, step)])
    if step*(stop - start) > 0:  # a non-null incr/decr range
        if step < 0:
            for i in frange(-start, -stop, -step, n):
                yield -i
        else:
            steps = round((stop - start)/step)
            while round(step*steps + start, n) < stop:
                steps += 1
            for i in range(steps):
                yield round(start + i*step, n)

答案 19 :(得分:-1)

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)

请注意Range的第一个字母是大写。对于Python中的函数,不鼓励使用此命名方法。如果需要,您可以将Range更改为drange或frange。 “范围”功能的行为与您希望的一样。您可以在此处查看手册[http://reference.wolfram.com/language/ref/Range.html]。

答案 20 :(得分:-1)

我认为有一个非常简单的答案可以真正模拟范围的所有功能,但同时包含浮点数和整数。在此解决方案中,您只需假设您的近似值默认为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)

答案 21 :(得分:-2)

Python中有浮点数的range()吗? 没有 使用此:

six