복붙노트

[PYTHON] 수레의 경우 range ()

PYTHON

수레의 경우 range ()

Python에서 float에 해당하는 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

해결법

  1. ==============================

    1.나는 내장 함수를 모른다. 그러나 이와 같은 것을 작성하는 것은 너무 복잡해서는 안된다.

    나는 내장 함수를 모른다. 그러나 이와 같은 것을 작성하는 것은 너무 복잡해서는 안된다.

    def frange(x, y, jump):
      while x < y:
        yield x
        x += jump
    

    언급에서 언급했듯이, 다음과 같은 예기치 않은 결과가 발생할 수 있습니다.

    >>> list(frange(0, 100, 0.1))[-1]
    99.9999999999986
    

    예상 된 결과를 얻으려면이 질문에서 다른 답변 중 하나를 사용하거나 언급 된 @Tadhg와 같이 점프 인수로 decimal.Decimal을 사용할 수 있습니다. 플로트가 아닌 문자열로 초기화해야합니다.

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

    2.다음 중 하나를 사용할 수 있습니다.

    다음 중 하나를 사용할 수 있습니다.

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

    또는 lambda / map을 사용하십시오.

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

    3.numpy.arange를 사용했지만 부동 소수점 오류로 인해 반환되는 요소의 수를 제어하는 ​​복잡성이있었습니다. 이제는 예를 들어 빈 공간을 사용합니다.

    numpy.arange를 사용했지만 부동 소수점 오류로 인해 반환되는 요소의 수를 제어하는 ​​복잡성이있었습니다. 이제는 예를 들어 빈 공간을 사용합니다.

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

    4.Pylab에는 frange (래퍼, matplotlib.mlab.frange)가 있습니다.

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

    5.열심히 평가 (2.x 범위) :

    열심히 평가 (2.x 범위) :

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

    느슨하게 평가 됨 (2.x xrange, 3.x 범위) :

    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.
    
  6. ==============================

    6.itertools 사용 : lazily 부동 소수점 범위 평가 :

    itertools 사용 : lazily 부동 소수점 범위 평가 :

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

    7.그러한 내장 함수는 없지만 다음 (Python 3 코드)를 사용하면 Python에서 허용하는 것처럼 안전하게 작업을 수행 할 수 있습니다.

    그러한 내장 함수는 없지만 다음 (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에서 사용할 수있는 코드

  8. ==============================

    8.나는 numeric_range 함수를 more-itertools 패키지에 추가하는 것을 도왔다.

    나는 numeric_range 함수를 more-itertools 패키지에 추가하는 것을 도왔다.

    more_itertools.numeric_range (start, stop, step)는 내장 함수 범위와 같은 역할을하지만 float, Decimal 및 Fraction 유형을 처리 할 수 ​​있습니다.

    >>> from more_itertools import numeric_range
    >>> tuple(numeric_range(.1, 5, 1))
    (0.1, 1.1, 2.1, 3.1, 4.1)
    
  9. ==============================

    9.표준 라이브러리에서 부동 소수점 범위 구현이없는 이유는 무엇입니까?

    표준 라이브러리에서 부동 소수점 범위 구현이없는 이유는 무엇입니까?

    여기에있는 모든 게시물에서 명확하게 알 수 있듯이 부동 소수점 버전의 range ()는 없습니다. 즉, range () 함수가 종종 인덱스 (물론 접근자를 의미) 생성기로 사용된다고 생각하면 생략하는 것이 좋습니다. 따라서 우리가 range (0,40)를 호출 할 때 우리는 0에서 시작하여 40까지의 값 40을 원하지만 40의 값을 포함하지 말라는 의미입니다.

    인덱스 생성은 인덱스의 개수만큼 중요하다고 생각할 때 표준 라이브러리에서 range ()의 float 구현을 사용하면 의미가 없습니다. 예를 들어 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))
    

    마찬가지로, 내장 라운드 함수를 사용하여 소수점 이하 자릿수를 지정할 수 있습니다.

    # 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
    

    또한, 스킵 파라미터가 스톱 값으로 나눌 수없는 경우, 후자의 문제에서 하품 간격이있을 수있다 :

    # 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를 사용하는 것입니다.

  10. ==============================

    10.numpy 등의 의존성이없는 솔루션은 kichik에 의해 제공되었지만 부동 소수점 연산으로 인해 예기치 않게 동작합니다. 나와 blubberdiblub이 지적한 것처럼 추가 요소가 쉽게 결과에 몰래 들어갑니다. 예를 들어, naive_frange (0.0, 1.0, 0.1)는 0.999 ...를 마지막 값으로 산출하여 총 11 개의 값을 생성합니다.

    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
    

    곱하기 때문에 반올림 오류가 누적되지 않습니다. 엡실론을 사용하면 곱셈의 반올림 오류를 처리 할 수 ​​있습니다. 물론 문제가 매우 작고 매우 커질 수 있습니다. 예상대로 :

    > 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로도 제공됩니다.

  11. ==============================

    11.나는 백분위 수를 초과하지 않는 소수점 이하 자릿수의 배정 밀도 부동 소수점 숫자의 튜플을 반환하는 함수를 작성했습니다. 문자열과 같은 범위 값을 구문 분석하고 초과 값을 분할하는 문제였습니다. UI 내에서 선택할 범위를 표시하는 데 사용합니다. 다른 사람이 유용하다고 생각하길 바랍니다.

    나는 백분위 수를 초과하지 않는 소수점 이하 자릿수의 배정 밀도 부동 소수점 숫자의 튜플을 반환하는 함수를 작성했습니다. 문자열과 같은 범위 값을 구문 분석하고 초과 값을 분할하는 문제였습니다. 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
    
  12. ==============================

    12.

    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의 함수에는 권장되지 않습니다. 원하는 경우 레인지를 레인지 (drange) 또는 프랜지 (frange)와 같은 것으로 변경할 수 있습니다. "범위"기능은 원하는대로 작동합니다. 여기에서 설명서를 확인할 수 있습니다 [http://reference.wolfram.com/language/ref/Range.html].

  13. ==============================

    13.나는 범위의 모든 특징을 실제로 모방하지만 플로트와 정수 모두에 대해 매우 간단한 대답이 있다고 생각합니다. 이 솔루션에서 근사치는 기본적으로 1e-7 (또는 선택한 것)이라고 가정하고 함수를 호출 할 때 변경할 수 있습니다.

    나는 범위의 모든 특징을 실제로 모방하지만 플로트와 정수 모두에 대해 매우 간단한 대답이 있다고 생각합니다. 이 솔루션에서 근사치는 기본적으로 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)
    
  14. ==============================

    14.Python에서 float에 해당하는 range ()가 있습니까? 아니 이것을 사용하십시오 :

    Python에서 float에 해당하는 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
    
  15. from https://stackoverflow.com/questions/7267226/range-for-floats by cc-by-sa and MIT license