मानक पुस्तकालय में कोई फ्लोटिंग प्वाइंट रेंज कार्यान्वयन क्यों नहीं है?
जैसा कि यहां के सभी पदों से स्पष्ट है, इसका कोई फ्लोटिंग पॉइंट संस्करण नहीं है range()
। उस ने कहा, चूक से समझ में आता है अगर हम मानते हैं कि range()
फ़ंक्शन को अक्सर एक इंडेक्स के रूप में उपयोग किया जाता है (और निश्चित रूप से, इसका मतलब एक एक्सेसर ) जनरेटर है। इसलिए, जब हम फोन करते हैं, तो हम कहते 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)
एक त्वरित तुलना और प्रदर्शन
बेशक, उपरोक्त चर्चा को देखते हुए, इन कार्यों में काफी सीमित उपयोग का मामला है। बहरहाल, यहाँ एक त्वरित तुलना है:
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 का उपयोग करना होगा।