दशमलव रेंज () स्टेप वैल्यू का उपयोग कैसे करें?


742

क्या 0 और 1 के बीच 0.1 से कदम रखने का एक तरीका है?

मैंने सोचा कि मैं इसे निम्न की तरह कर सकता हूं, लेकिन यह विफल रहा:

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

इसके बजाय, यह कहता है कि चरण तर्क शून्य नहीं हो सकता है, जिसकी मुझे उम्मीद नहीं थी।


17
int (0.1) == 0, इसलिए चरण वास्तव में शून्य है। यह अप्रत्याशित हो सकता है, लेकिन यह शून्य है। आप इस तथ्य को प्रतिबिंबित करने के लिए अपने प्रश्न को शांत करना चाह सकते हैं कि आपने यह उम्मीद नहीं की थी। "यह नहीं है" कहना गलत और भ्रामक है।
S.Lott

3
BTW एक लघु-लाइनर का उपयोग कर रोल किया जा सकता है itertools.takewhileऔर itertools.count। यह drangeप्रदर्शन-वार से बेहतर नहीं है , हालांकि।
कोस

1
यह शर्मनाक है कि अजगर की सीमा इस बात की अनुमति नहीं देती है, यह देखते हुए कि एक जनरेटर को लागू करना कितना आसान है, जो राउंडिंग त्रुटियों को जमा किए बिना भी ऐसा करता है। बिल्ली, यहां तक ​​कि seqGNU कोरुटिल्स में उपकरण एक को seq 0 0.1 1बिना गोल त्रुटियों के करने की अनुमति देता है !
जॉस

3
@josch: seqसी का उपयोग करता है long doubleप्रकार आंतरिक रूप से, और है गोलाई त्रुटियों के अधीन है। मेरी मशीन पर उदाहरण के लिए, seq 0 0.1 1देता है 1(उम्मीद के रूप में) अपने पिछले आउटपुट के रूप में है, लेकिन seq 1 0.1 2देता है 1.9पिछले आउटपुट के रूप में (बजाय उम्मीद 2)।
मार्क डिकिंसन

सुविधा के लिए, @ कोस के सुझाव को ( itertools.takewhile(lambda x: (x+0.05)<1, itertools.count(0,0.1))या itertools.islice(itertools.count(0,0.1), 10)आपके पास होने के बाद import itertools) लागू किया जा सकता है , हालांकि मैंने यह परीक्षण नहीं किया है कि कौन अधिक कुशल है
अनाम

जवाबों:


905

सीधे एक दशमलव चरण का उपयोग करने के बजाय, यह इस बात को व्यक्त करने के लिए अधिक सुरक्षित है कि आप कितने अंक चाहते हैं। अन्यथा, फ़्लोटिंग-पॉइंट राउंडिंग त्रुटि आपको गलत परिणाम देने की संभावना है।

आप NumPy लाइब्रेरी से लिन्स्पेस फ़ंक्शन का उपयोग कर सकते हैं (जो मानक लाइब्रेरी का हिस्सा नहीं है लेकिन इसे प्राप्त करना अपेक्षाकृत आसान है)। लौटने के लिए कई बिंदुओं को लेता है, और आपको सही समापन बिंदु को शामिल करने या न करने की भी अनुमति देता है:linspace

>>> np.linspace(0,1,11)
array([ 0. ,  0.1,  0.2,  0.3,  0.4,  0.5,  0.6,  0.7,  0.8,  0.9,  1. ])
>>> np.linspace(0,1,10,endpoint=False)
array([ 0. ,  0.1,  0.2,  0.3,  0.4,  0.5,  0.6,  0.7,  0.8,  0.9])

यदि आप वास्तव में फ्लोटिंग-पॉइंट स्टेप वैल्यू का उपयोग करना चाहते हैं, तो आप कर सकते हैं numpy.arange

>>> import numpy as np
>>> np.arange(0.0, 1.0, 0.1)
array([ 0. ,  0.1,  0.2,  0.3,  0.4,  0.5,  0.6,  0.7,  0.8,  0.9])

फ्लोटिंग प्वाइंट पूर्णांकन त्रुटि होगा हालांकि समस्याओं के कारण,। यहां एक सरल मामला है जहां गोलाई त्रुटि के कारण arangeलंबाई -4 सरणी का उत्पादन होता है जब इसे केवल 3 नंबर का उत्पादन करना चाहिए:

>>> numpy.arange(1, 1.3, 0.1)
array([1. , 1.1, 1.2, 1.3])

51
numpy अजगर का ऐसा सर्वव्यापी घटक है कि मैं इस उत्तर को सभी का सबसे 'पायथोनिक' मानता हूं।
हवाई

21
@AndreTerra समस्या यह है कि @ numpy @ एक तृतीय पक्ष पैकेज है और निर्भरता-प्रबंधन, भंडारण (स्वयं पैकेज के लिए) आदि के मामले में बहुत अधिक उपरि जोड़ता है। डेवलपर क्या कर रहा है, इसके आधार पर इसका उपयोग करना असंभव हो सकता है। यह।
rbaleksandar

मुझे क्षमा करें, लेकिन मैं पिछले हिस्से में फ्लोटिंग पॉइंट राउंडिंग एरर को नहीं समझ पाया था np.linspace(1.,1.3,4)और np.arange(1.,1.3,0.1)बिल्कुल वही आउटपुट दे रहा था
डेडकोड

4
@deadcode इसका कारण यह है कि np.arange को एक श्रेणी [start,stop)(यानी छोड़कर stop) का उत्पादन करने के लिए परिभाषित किया गया है , इसलिए किसी को 1.3 की सूची में शामिल होने की उम्मीद नहीं होगी। इस सवाल को देखें कि यह अभी भी क्यों शामिल है और इसके खिलाफ क्या करना है।
डेनिस

5
किसी पैकेज का कितना उपयोग किया जाता है, यकीनन इस बात का कोई संकेतक नहीं है कि यह "पायथोनिक" है या नहीं।
एलेक्स हॉल

213

पायथन की रेंज () केवल पूर्णांक कर सकती है, फ़्लोटिंग पॉइंट नहीं। अपने विशिष्ट मामले में, आप इसके बजाय सूची समझ का उपयोग कर सकते हैं:

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

(उस अभिव्यक्ति के साथ कॉल करने के लिए कॉल बदलें।)

अधिक सामान्य मामले के लिए, आप एक कस्टम फ़ंक्शन या जनरेटर लिखना चाह सकते हैं।


36
इससे भी बेहतर, अगर आप अजगर 2.4+ के साथ काम कर रहे हैं तो आप एक जनरेटर की समझ का उपयोग कर सकते हैं। (x * 0.1 for x in range(0, 10))
JAB

42
इससे भी बेहतर, x/10इसके बजाय x * 0.1: डी कुछ भी विशेष नहीं है, लेकिन कुछ संख्याएँ अधिक सटीक होंगी, जैसे कि 3*0.1आपके लिए 0.30000000000000004, जबकि 3/10 के लिए आपको 0.3:)
ब्लोक

4
3/10 मुझे 0 देता है, न कि 0.3। 3 / 10.0 0.29999999999999999 में देता है। पायथन 2.6।

19
@LarsWirzenius: पायथन 2.2+ में, from __future__ import division; 3/100.3 देता है। यह व्यवहार पायथन 3.x में डिफ़ॉल्ट है।
बेंजामिन हॉजसन

2
राउंड फंक्शन का इस्तेमाल lst = [round (x * 0.10,2) के लिए x में रेंज (0,10)]
MARK

148

'Xrange ([प्रारंभ], रोक [, कदम])' पर बिल्डिंग , आप एक जनरेटर को परिभाषित कर सकते हैं जो आपके द्वारा चुने गए किसी भी प्रकार को स्वीकार करता है और उत्पन्न करता है (सहायक प्रकारों के लिए छड़ी +और <):

>>> def drange(start, stop, step):
...     r = start
...     while r < stop:
...         yield r
...         r += step
...         
>>> i0=drange(0.0, 1.0, 0.1)
>>> ["%g" % x for x in i0]
['0', '0.1', '0.2', '0.3', '0.4', '0.5', '0.6', '0.7', '0.8', '0.9', '1']
>>> 

45
इससे राउंडऑफ की समस्या है। कृपया यहाँ देखें: code.activestate.com/recipes/66472
क्रिश्चियन Oudard

मैं दूसरी दिशा के लिए इसे थोड़ा बढ़ा दूंगा (जबकि आर> स्टॉप) और इसके विपरीत दिशा देने के लिए एक संगत आर - = चरण।
user318904

1
मैंने ऊपर बताई गई फ्लोट सटीक समस्याओं के बिना एक xfrange फंक्शन किया। इसे देखें;) stackoverflow.com/questions/477486/…
कार्लोस वेगा

1
आप गोलाई त्रुटियों को जमा कर रहे हैं। कृपया इसके बजाय इसका उपयोग करें: `i = 0; r = start जबकि r <stop: i + = 1; r = start + i * step; r` उपज
Cees Timmerman

1
यह pythoncentral.io/pythons-range-function-explained (और अन्य पायथन प्रलेखन स्रोत) से है
Apostolos

31

iलूप के लिए परिमाण को बढ़ाएं और फिर इसे ज़रूरत पड़ने पर कम करें।

for i * 100 in range(0, 100, 10):
    print i / 100.0

संपादित करें: मैं ईमानदारी से याद नहीं कर सकता कि मैंने क्यों सोचा कि यह वाक्यात्मक रूप से काम करेगा

for i in range(0, 11, 1):
    print i / 10.0

वह वांछित आउटपुट होना चाहिए।


मुझे लगता है कि आप एक ही फ़ंक्शन कम से कम उपयोग करके, उस श्रेणी () को पूर्णांक से काम करते हैं, जिस स्थिति में यह एकमात्र समाधान होगा।
मैथ्यू शारले

1
@ cmsjr रचनात्मक: डी बस एक छोटी सी चीज: यदि आप पायथन 2.x का उपयोग कर रहे हैं तो परिणाम को रौंदने से अजगर को रखने के लिए 100.0 से विभाजित करें। मुझे लगता है कि 3.0 में, यह काम करेगा क्योंकि आपने इसे कोडित किया है।
दना

2
for i * 100 in range(0, 100, 10): SyntaxError: ऑपरेटर को असाइन नहीं कर सकता है
ऐनी वैन रोसुम

25

scipyएक अंतर्निहित फ़ंक्शन है arangeजो range()फ्लोट हैंडलिंग की आपकी आवश्यकता को पूरा करने के लिए पायथन के कंस्ट्रक्टर को सामान्य करता है ।

from scipy import arange


8
यह वास्तव में वही है जो arangeआप सुन्न में पा सकते हैं: >>> import scipy >>> import numpy >>> numpy.arange is scipy.arangeवापस आ जाएगा True
Ireilicht

from nump import arange as range
शूरमौस

24

NumPy थोड़ा ओवरकिल है, मुझे लगता है।

[p/10 for p in range(0, 10)]
[0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9]

आम तौर पर, एक कदम-दर-कदम आप 1/xकरने के yलिए

x=100
y=2
[p/x for p in range(0, int(x*y))]
[0.0, 0.01, 0.02, 0.03, ..., 1.97, 1.98, 1.99]

( 1/xजब मैंने परीक्षण किया तो कम गोलाई उत्पन्न हुई)।


18

आर के seq फ़ंक्शन के समान , यह किसी भी क्रम में एक अनुक्रम लौटाता है जिसे सही चरण मान दिया जाता है। अंतिम मान स्टॉप वैल्यू के बराबर है।

def seq(start, stop, step=1):
    n = int(round((stop - start)/float(step)))
    if n > 1:
        return([start + step*i for i in range(n+1)])
    elif n == 1:
        return([start])
    else:
        return([])

परिणाम

seq(1, 5, 0.5)

[1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0]

seq(10, 0, -1)

[१०, ९, 8, 8, ६, ५, ४, ३, २, १, ०]

seq(10, 0, -2)

[१०, 6, ६, ४, २, ०]

seq(1, 1)

[१]


2
यह किसी ऐसे व्यक्ति के लिए एक शानदार उत्तर है जो इसे बहुत अधिक मात्रा में प्राप्त किए बिना प्राप्त करना चाहता है।
चनि

1
यह लगभग वही था जो मैं खोज रहा था - ध्यान दें कि seq(0.5, 3.0)रिटर्न [0.5, 1.5, 2.5, 3.5]। पिछले प्रविष्टियों बाहर के रेंज में किया जा रहा से बचने के लिए की जगह n = int(round(...के साथ n = int(floor(...लाइन के साथ from math import floorशीर्ष (ऊपर से def seq(...)।
फ्रेंडएफ़एक्स

2
@FriendFX ऐसा न करें! यदि floorउपयोग किया जाता है, seq(0.2, 0.9, 0.1)तो सही समापन बिंदु तक पहुंचने में विफल हो जाएगा और वापस आ जाएगा[0.2, 0.30000000000000004, 0.4, 0.5, 0.6000000000000001, 0.7, 0.8]
fdermishin

@ user502144: अच्छा पकड़, धन्यवाद। मुझे लगता है कि मुझे इसे सामान्य बनाए रखने के लिए अधिक जटिल समाधानों में से एक के लिए समझौता करना होगा।
फ्रेंड एफएक्स

14

रेंज () अंतर्निहित फ़ंक्शन पूर्णांक मानों का एक क्रम देता है, मुझे डर है, इसलिए आप इसका उपयोग दशमलव चरण करने के लिए नहीं कर सकते।

मैं कहूंगा कि बस थोड़ी देर के लूप का उपयोग करें:

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

यदि आप उत्सुक हैं, तो पायथन आपके 0.1 से 0 को परिवर्तित कर रहा है, यही कारण है कि यह आपको बता रहा है कि तर्क शून्य नहीं हो सकता है।


2
यह मत करो! .110 बार जोड़ना जोड़ने के समान नहीं है 1! docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
cat

12

यहाँ 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)

उपयोग उदाहरण:

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

पूर्णता के लिए, आपको नमूना_काउंट चर के लिए पूर्ण मान की गणना करनी चाहिए, इस तरह आपका कार्य एक नकारात्मक शुरुआत के लिए भी काम करेगा (यानी -10 से 10 तक)
डेलेमेन

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

पायथन 2.7x में आपको इसका परिणाम मिलता है:

[0.0, 0.1, 0.2, 0.30000000000000004, 0.4, 0.5, 0.6000000000000001, 0.7000000000000001, 0.8, 0.9]

लेकिन अगर आप उपयोग करते हैं:

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

आपको वांछित:

[0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9]



5

और यदि आप अक्सर ऐसा करते हैं, तो आप उत्पन्न सूची को सहेजना चाह सकते हैं r

r=map(lambda x: x/10.0,range(0,10))
for i in r:
    print i

5

more_itertoolsएक तृतीय-पक्ष पुस्तकालय है जो एक numeric_rangeउपकरण को लागू करता है:

import more_itertools as mit


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

उत्पादन

0.0
0.1
0.2
0.3
0.4
0.5
0.6
0.7
0.8
0.9

यह उपकरण Decimalऔर के लिए भी काम करता है Fraction


4

मेरे संस्करण शिफ्ट के लिए गुणा सूचक बनाने के लिए मूल रेंज फ़ंक्शन का उपयोग करते हैं। यह मूल श्रेणी फ़ंक्शन के समान सिंटैक्स की अनुमति देता है। मैंने दो संस्करण बनाए हैं, एक फ्लोट का उपयोग कर रहा है, और एक दशमलव का उपयोग कर रहा है, क्योंकि मैंने पाया कि कुछ मामलों में मैं फ्लोटिंग पॉइंट अंकगणित द्वारा शुरू किए गए राउंडऑफ बहाव से बचना चाहता था।

यह सीमा / xrange में रिक्त सेट परिणामों के अनुरूप है।

या तो फ़ंक्शन के लिए केवल एक संख्यात्मक मान पास करना इनपुट पैरामीटर के पूर्णांक छत मूल्य के लिए मानक रेंज आउटपुट लौटाएगा (इसलिए यदि आपने इसे 5.5 दिया था, तो यह रेंज (6) वापस आ जाएगी।)

संपादित करें: नीचे दिया गया कोड अब 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)) # []

frangeअगर स्टॉप है तो काम कैसे हो सकता है None? कोड का वह हिस्सा अब चरण आकार पर भी विचार नहीं करता है।
जॉस

1
@ जोश rangeके दो हस्ताक्षर हैं: range(stop)जो एक डिफ़ॉल्ट मानता है start=0, step=1, और range(start, stop, step), जहां कोई धारणा नहीं बनाई जाती है। frangeयह दर्शाता है। का उपयोग करते समय range(stop)हस्ताक्षर, दोनों frangeऔर drange1 से 0 और वेतन वृद्धि पर शुरू है, तो उनके व्यवहार नियमित रूप से समान है range(stop)निकटतम पूर्णांक में पूर्णांकित कर विराम के साथ व्यवहार।
निसान।

4

फ्लोट चरणों के साथ रेंज प्राप्त करने के लिए यह मेरा समाधान है।
इस फ़ंक्शन का उपयोग करना आवश्यक नहीं है कि यह खस्ता आयात हो, और न ही इसे स्थापित करें।
मुझे पूरा यकीन है कि इसे बेहतर और अनुकूलित किया जा सकता है। बेझिझक इसे करें और इसे यहां पोस्ट करें।

from __future__ import division
from math import log

def xfrange(start, stop, step):

    old_start = start #backup this value

    digits = int(round(log(10000, 10)))+1 #get number of digits
    magnitude = 10**digits
    stop = int(magnitude * stop) #convert from 
    step = int(magnitude * step) #0.1 to 10 (e.g.)

    if start == 0:
        start = 10**(digits-1)
    else:
        start = 10**(digits)*start

    data = []   #create array

    #calc number of iterations
    end_loop = int((stop-start)//step)
    if old_start == 0:
        end_loop += 1

    acc = start

    for i in xrange(0, end_loop):
        data.append(acc/magnitude)
        acc += step

    return data

print xfrange(1, 2.1, 0.1)
print xfrange(0, 1.1, 0.1)
print xfrange(-1, 0.1, 0.1)

आउटपुट है:

[1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0]
[0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.1]
[-1.0, -0.9, -0.8, -0.7, -0.6, -0.5, -0.4, -0.3, -0.2, -0.1, 0.0]

1
यदि स्टॉप वैल्यू के 1 चरण के भीतर अंतिम मान गायब है, तो एक त्रुटि है। यानी xfrange (1,10,2) केवल 1,3,5,7 करता है, लापता 9
लोब

संदर्भ और अन्य पाठकों के लिए, कृपया इस कार्यान्वयन की तुलना इस stackoverflow.com/a/477610/54964 से करें । इससे फ्लोट की बड़ी समस्या नहीं लगती है।
लेओ लेपोल्ड हर्ट्ज़ '

@carlosvega क्या आप पुष्टि कर सकते हैं कि लोब को उसका परिणाम क्यों मिलता है?
लेओ लेपोल्ड हर्ट्ज़ '12

3

बुटीक की पूर्णता के लिए, एक कार्यात्मक समाधान:

def frange(a,b,s):
  return [] if s > 0 and a > b or s < 0 and a < b or s==0 else [a]+frange(a+s,b,s)

2

आप इस फ़ंक्शन का उपयोग कर सकते हैं:

def frange(start,end,step):
    return map(lambda x: x*step, range(int(start*1./step),int(end*1./step)))

सही ढंग से काम नहीं करता है, जैसेlist(frange(99.8, 100.1, 0.1)) => [99.7, 99.80000000000001, 99.9]
Shai Coleman

2

चाल से बचने के लिए दौर बंद समस्या , सीमा के माध्यम से स्थानांतरित करने के लिए एक अलग नंबर का उपयोग करने के लिए है कि शुरू होता है और आधा कदम से आगे शुरू

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

वैकल्पिक रूप से, numpy.arangeइस्तेमाल किया जा सकता है।


2

यह Numpy लाइब्रेरी का उपयोग करके किया जा सकता है। अरेंज () फ़ंक्शन फ्लोट में चरणों की अनुमति देता है। लेकिन, यह एक सुव्यवस्थित सरणी देता है जिसे हमारी सुविधा के लिए सूची () का उपयोग करके परिवर्तित किया जा सकता है।

for i in np.arange(0, 1, 0.1).tolist():
   print i

2

मेरा उत्तर मानचित्र (), NumPy की आवश्यकता के बिना, और लंबोदर (हालांकि आप कर सकते हैं) का उपयोग किए बिना दूसरों के समान है। Dt के चरणों में 0.0 से t_max तक फ्लोट मानों की सूची प्राप्त करने के लिए:

def xdt(n):
    return dt*float(n)
tlist  = map(xdt, range(int(t_max/dt)+1))

2

पायथन 3 डॉक्स में सुझाए गए घोल का अभी तक किसी ने भी उल्लेख नहीं किया है :

यह सभी देखें:

  • Linspace नुस्खा शो कैसे है कि चल बिन्दु अनुप्रयोगों के लिए उपयुक्त रेंज के एक आलसी संस्करण को लागू करने के लिए।

एक बार परिभाषित करने के बाद, नुस्खा का उपयोग करना आसान है और numpyकिसी अन्य बाहरी पुस्तकालय की आवश्यकता नहीं है , लेकिन कार्य करता है numpy.linspace()। ध्यान दें कि एक stepतर्क के बजाय , तीसरा numतर्क उदाहरण के लिए वांछित मानों की संख्या को निर्दिष्ट करता है:

print(linspace(0, 10, 5))
# linspace(0, 10, 5)
print(list(linspace(0, 10, 5)))
# [0.0, 2.5, 5.0, 7.5, 10]

मैं नीचे एंड्रयू बर्नर्ट से पूर्ण पायथन 3 नुस्खा का एक संशोधित संस्करण उद्धृत करता हूं:

import collections.abc
import numbers

class linspace(collections.abc.Sequence):
    """linspace(start, stop, num) -> linspace object

    Return a virtual sequence of num numbers from start to stop (inclusive).

    If you need a half-open range, use linspace(start, stop, num+1)[:-1].
    """
    def __init__(self, start, stop, num):
        if not isinstance(num, numbers.Integral) or num <= 1:
            raise ValueError('num must be an integer > 1')
        self.start, self.stop, self.num = start, stop, num
        self.step = (stop-start)/(num-1)
    def __len__(self):
        return self.num
    def __getitem__(self, i):
        if isinstance(i, slice):
            return [self[x] for x in range(*i.indices(len(self)))]
        if i < 0:
            i = self.num + i
        if i >= self.num:
            raise IndexError('linspace object index out of range')
        if i == self.num-1:
            return self.stop
        return self.start + i*self.step
    def __repr__(self):
        return '{}({}, {}, {})'.format(type(self).__name__,
                                       self.start, self.stop, self.num)
    def __eq__(self, other):
        if not isinstance(other, linspace):
            return False
        return ((self.start, self.stop, self.num) ==
                (other.start, other.stop, other.num))
    def __ne__(self, other):
        return not self==other
    def __hash__(self):
        return hash((type(self), self.start, self.stop, self.num))

2

फ्लोट सटीक मुद्दों का मुकाबला करने के लिए, आप Decimalमॉड्यूल का उपयोग कर सकते हैं ।

यह करने के लिए परिवर्तित करने की एक अतिरिक्त प्रयास की मांग Decimalसे intया floatजबकि कोड लिखने, लेकिन आप के बजाय पारित कर सकते हैं strऔर समारोह को संशोधित करता है, तो सुविधा की इस प्रकार की वास्तव में आवश्यक है।

from decimal import Decimal
from decimal import Decimal as D


def decimal_range(*args):

    zero, one = Decimal('0'), Decimal('1')

    if len(args) == 1:
        start, stop, step = zero, args[0], one
    elif len(args) == 2:
        start, stop, step = args + (one,)
    elif len(args) == 3:
        start, stop, step = args
    else:
        raise ValueError('Expected 1 or 2 arguments, got %s' % len(args))

    if not all([type(arg) == Decimal for arg in (start, stop, step)]):
        raise ValueError('Arguments must be passed as <type: Decimal>')

    # neglect bad cases
    if (start == stop) or (start > stop and step >= zero) or \
                          (start < stop and step <= zero):
        return []

    current = start
    while abs(current) < abs(stop):
        yield current
        current += step

नमूना आउटपुट -

list(decimal_range(D('2')))
# [Decimal('0'), Decimal('1')]
list(decimal_range(D('2'), D('4.5')))
# [Decimal('2'), Decimal('3'), Decimal('4')]
list(decimal_range(D('2'), D('4.5'), D('0.5')))
# [Decimal('2'), Decimal('2.5'), Decimal('3.0'), Decimal('3.5'), Decimal('4.0')]
list(decimal_range(D('2'), D('4.5'), D('-0.5')))
# []
list(decimal_range(D('2'), D('-4.5'), D('-0.5')))
# [Decimal('2'),
#  Decimal('1.5'),
#  Decimal('1.0'),
#  Decimal('0.5'),
#  Decimal('0.0'),
#  Decimal('-0.5'),
#  Decimal('-1.0'),
#  Decimal('-1.5'),
#  Decimal('-2.0'),
#  Decimal('-2.5'),
#  Decimal('-3.0'),
#  Decimal('-3.5'),
#  Decimal('-4.0')]

2
इसी तरह के Decimalइनपुट्स, समान np.arangeकाम करते हैं:np.arange(Decimal('-2.0'), Decimal('2.0'), Decimal('0.1'))
hpaulj

2
हां, धन्यवाद। हालाँकि, इसके लिए बाहरी (संख्यात्मक) परिवाद की आवश्यकता होगी।
shad0w_wa1k3r

1

कदम पर एक गलत संकेत की संभावना के लिए ऑटो-सुधार जोड़ें:

def frange(start,step,stop):
    step *= 2*((stop>start)^(step<0))-1
    return [start+i*step for i in range(int((stop-start)/step))]

1

मेरा समाधान:

def seq(start, stop, step=1, digit=0):
    x = float(start)
    v = []
    while x <= stop:
        v.append(round(x,digit))
        x += step
    return v

1

सबसे अच्छा समाधान: कोई गोल त्रुटि
_________________________________________________________________________________________________

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

_________________________________________________________________________________________

या, सेट डेटा पॉइंट्स (जैसे निरंतर फ़ंक्शन) के बजाय एक निर्धारित सीमा के लिए उपयोग करें:

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

किसी फ़ंक्शन को लागू करने के लिए: के x / pow(step, -1)साथ बदलें f( x / pow(step, -1) ), और परिभाषित करें f
उदाहरण के लिए:

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

1

स्टार्ट और स्टॉप एक या दूसरे के बजाय समावेशी हैं (आमतौर पर स्टॉप को बाहर रखा गया है) और आयात के बिना, और जनरेटर का उपयोग करना

def rangef(start, stop, step, fround=5):
    """
    Yields sequence of numbers from start (inclusive) to stop (inclusive)
    by step (increment) with rounding set to n digits.

    :param start: start of sequence
    :param stop: end of sequence
    :param step: int or float increment (e.g. 1 or 0.001)
    :param fround: float rounding, n decimal places
    :return:
    """
    try:
        i = 0
        while stop >= start and step > 0:
            if i==0:
                yield start
            elif start >= stop:
                yield stop
            elif start < stop:
                if start == 0:
                    yield 0
                if start != 0:
                    yield start
            i += 1
            start += step
            start = round(start, fround)
        else:
            pass
    except TypeError as e:
        yield "type-error({})".format(e)
    else:
        pass


# passing
print(list(rangef(-100.0,10.0,1)))
print(list(rangef(-100,0,0.5)))
print(list(rangef(-1,1,0.2)))
print(list(rangef(-1,1,0.1)))
print(list(rangef(-1,1,0.05)))
print(list(rangef(-1,1,0.02)))
print(list(rangef(-1,1,0.01)))
print(list(rangef(-1,1,0.005)))
# failing: type-error:
print(list(rangef("1","10","1")))
print(list(rangef(1,10,"1")))

पायथन 3.6.2 (v3.6.2: 5fd33b5, Jul 8 2017, 04:57:36) [MSC v.1900 64 बिट (AMD64)]


1

मुझे पता है कि मुझे यहां पार्टी में देर हो रही है, लेकिन यहाँ एक तुच्छ जनरेटर समाधान है जो 3.6 में काम कर रहा है:

def floatRange(*args):
    start, step = 0, 1
    if len(args) == 1:
        stop = args[0]
    elif len(args) == 2:
        start, stop = args[0], args[1]
    elif len(args) == 3:
        start, stop, step = args[0], args[1], args[2]
    else:
        raise TypeError("floatRange accepts 1, 2, or 3 arguments. ({0} given)".format(len(args)))
    for num in start, step, stop:
        if not isinstance(num, (int, float)):
            raise TypeError("floatRange only accepts float and integer arguments. ({0} : {1} given)".format(type(num), str(num)))
    for x in range(int((stop-start)/step)):
        yield start + (x * step)
    return

तब आप इसे मूल की तरह कह सकते हैं range()... कोई त्रुटि से निपटने नहीं है, लेकिन मुझे बताएं कि क्या कोई त्रुटि है जिसे यथोचित पकड़ा जा सकता है, और मैं अपडेट करूंगा। या आप इसे अपडेट कर सकते हैं। यह StackOverflow है।


0

यहाँ मेरा समाधान है जो फ्लोट_ेंज (-1, 0, 0.01) के साथ ठीक काम करता है और फ्लोटिंग पॉइंट प्रतिनिधित्व त्रुटियों के बिना काम करता है। यह बहुत तेज़ नहीं है, लेकिन ठीक काम करता है:

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

मैं केवल एक शुरुआत कर रहा हूं, लेकिन मुझे एक ही समस्या थी, जब कुछ गणनाओं का अनुकरण करते हुए। यहां बताया गया है कि मैंने इसे कैसे काम करने का प्रयास किया, जो दशमलव चरणों के साथ काम करता है।

मैं काफी आलसी भी हूं और इसलिए मुझे अपना रेंज फंक्शन लिखना मुश्किल लगा।

मूल रूप से मैंने जो कुछ भी किया है वह मेरे xrange(0.0, 1.0, 0.01)लिए बदल गया है xrange(0, 100, 1)और 100.0लूप के अंदर विभाजन का उपयोग किया है । मैं भी चिंतित था, अगर राउंडिंग गलतियाँ होंगी। इसलिए मैंने परीक्षण करने का फैसला किया, चाहे कोई भी हो। अब मैंने सुना है, कि अगर 0.01एक गणना से उदाहरण के लिए फ्लोट नहीं है0.01 तुलना करना उन्हें फाल्स लौटाना चाहिए (यदि मैं गलत हूं, तो कृपया मुझे बताएं)।

इसलिए मैंने परीक्षण करने का निर्णय लिया कि क्या मेरा हल एक लघु परीक्षण चलाकर मेरी सीमा के लिए काम करेगा:

for d100 in xrange(0, 100, 1):
    d = d100 / 100.0
    fl = float("0.00"[:4 - len(str(d100))] + str(d100))
    print d, "=", fl , d == fl

और इसने प्रत्येक के लिए ट्रू प्रिंट किया।

अब, अगर मुझे यह पूरी तरह से गलत लग रहा है, तो कृपया मुझे बताएं।


0

यह एक लाइनर आपके कोड को अव्यवस्थित नहीं करेगा। कदम पैरामीटर का संकेत महत्वपूर्ण है।

def frange(start, stop, step):
    return [x*step+start for x in range(0,round(abs((stop-start)/step)+0.5001),
        int((stop-start)/step<0)*-2+1)]
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.