How to use a decimal range() step value?

前端 未结 30 2173
醉话见心
醉话见心 2020-11-21 22:34

Is there a way to step between 0 and 1 by 0.1?

I thought I could do it like the following, but it failed:

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


        
相关标签:
30条回答
  • 2020-11-21 23:11

    scipy has a built in function arange which generalizes Python's range() constructor to satisfy your requirement of float handling.

    from scipy import arange

    0 讨论(0)
  • 2020-11-21 23:11

    more_itertools is a third-party library that implements a numeric_range tool:

    import more_itertools as mit
    
    
    for x in mit.numeric_range(0, 1, 0.1):
        print("{:.1f}".format(x))
    

    Output

    0.0
    0.1
    0.2
    0.3
    0.4
    0.5
    0.6
    0.7
    0.8
    0.9
    

    This tool also works for Decimal and Fraction.

    0 讨论(0)
  • 2020-11-21 23:12

    The range() built-in function returns a sequence of integer values, I'm afraid, so you can't use it to do a decimal step.

    I'd say just use a while loop:

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

    If you're curious, Python is converting your 0.1 to 0, which is why it's telling you the argument can't be zero.

    0 讨论(0)
  • 2020-11-21 23:12

    Add auto-correction for the possibility of an incorrect sign on step:

    def frange(start,step,stop):
        step *= 2*((stop>start)^(step<0))-1
        return [start+i*step for i in range(int((stop-start)/step))]
    
    0 讨论(0)
  • 2020-11-21 23:12

    Here is my solution which works fine with float_range(-1, 0, 0.01) and works without floating point representation errors. It is not very fast, but works fine:

    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]
    
    0 讨论(0)
  • 2020-11-21 23:16

    Best Solution: no rounding error

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

    Or, for a set range instead of set data points (e.g. continuous function), use:

    >>> step = .1
    >>> rnge = 1     # NOTE range = 1, i.e. 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]
    

    To implement a function: replace x / pow(step, -1) with f( x / pow(step, -1) ), and define f.
    For example:

    >>> import math
    >>> def f(x):
            return math.sin(x)
    
    >>> step = .1
    >>> rnge = 1     # NOTE range = 1, i.e. 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]
    
    0 讨论(0)
提交回复
热议问题