How to use a decimal range() step value?

前端 未结 30 2175
醉话见心
醉话见心 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:18

    Python's range() can only do integers, not floating point. In your specific case, you can use a list comprehension instead:

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

    (Replace the call to range with that expression.)

    For the more general case, you may want to write a custom function or generator.

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

    Here's a solution using 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)
    

    Usage Example:

    for i in seq(0, 1, 0.1):
        print(i)
    
    0 讨论(0)
  • 2020-11-21 23:21

    The trick to avoid round-off problem is to use a separate number to move through the range, that starts and half the step ahead of start.

    # floating point range
    def frange(a, b, stp=1.0):
      i = a+stp/2.0
      while i<b:
        yield a
        a += stp
        i += stp
    

    Alternatively, numpy.arange can be used.

    0 讨论(0)
  • 2020-11-21 23:23
    import numpy as np
    for i in np.arange(0, 1, 0.1): 
        print i 
    
    0 讨论(0)
  • 2020-11-21 23:24

    My versions use the original range function to create multiplicative indices for the shift. This allows same syntax to the original range function. I have made two versions, one using float, and one using Decimal, because I found that in some cases I wanted to avoid the roundoff drift introduced by the floating point arithmetic.

    It is consistent with empty set results as in range/xrange.

    Passing only a single numeric value to either function will return the standard range output to the integer ceiling value of the input parameter (so if you gave it 5.5, it would return range(6).)

    Edit: the code below is now available as package on pypi: Franges

    ## frange.py
    from math import ceil
    # find best range function available to version (2.7.x / 3.x.x)
    try:
        _xrange = xrange
    except NameError:
        _xrange = range
    
    def frange(start, stop = None, step = 1):
        """frange generates a set of floating point values over the 
        range [start, stop) with step size step
    
        frange([start,] stop [, step ])"""
    
        if stop is None:
            for x in _xrange(int(ceil(start))):
                yield x
        else:
            # create a generator expression for the index values
            indices = (i for i in _xrange(0, int((stop-start)/step)))  
            # yield results
            for i in indices:
                yield start + step*i
    
    ## drange.py
    import decimal
    from math import ceil
    # find best range function available to version (2.7.x / 3.x.x)
    try:
        _xrange = xrange
    except NameError:
        _xrange = range
    
    def drange(start, stop = None, step = 1, precision = None):
        """drange generates a set of Decimal values over the
        range [start, stop) with step size step
    
        drange([start,] stop, [step [,precision]])"""
    
        if stop is None:
            for x in _xrange(int(ceil(start))):
                yield x
        else:
            # find precision
            if precision is not None:
                decimal.getcontext().prec = precision
            # convert values to decimals
            start = decimal.Decimal(start)
            stop = decimal.Decimal(stop)
            step = decimal.Decimal(step)
            # create a generator expression for the index values
            indices = (
                i for i in _xrange(
                    0, 
                    ((stop-start)/step).to_integral_value()
                )
            )  
            # yield results
            for i in indices:
                yield float(start + step*i)
    
    ## testranges.py
    import frange
    import drange
    list(frange.frange(0, 2, 0.5)) # [0.0, 0.5, 1.0, 1.5]
    list(drange.drange(0, 2, 0.5, precision = 6)) # [0.0, 0.5, 1.0, 1.5]
    list(frange.frange(3)) # [0, 1, 2]
    list(frange.frange(3.5)) # [0, 1, 2, 3]
    list(frange.frange(0,10, -1)) # []
    
    0 讨论(0)
  • 2020-11-21 23:24

    You can use this function:

    def frange(start,end,step):
        return map(lambda x: x*step, range(int(start*1./step),int(end*1./step)))
    
    0 讨论(0)
提交回复
热议问题