यदि कोई स्ट्रिंग एक संख्या (फ्लोट) है तो मैं कैसे जांच सकता हूं?


1605

यह जांचने का सबसे अच्छा संभव तरीका है कि क्या पायथन में एक संख्या के रूप में एक स्ट्रिंग का प्रतिनिधित्व किया जा सकता है?

मेरे पास अभी जो फंक्शन है वह है:

def is_number(s):
    try:
        float(s)
        return True
    except ValueError:
        return False

जो न केवल बदसूरत और धीमा है, बल्कि भद्दा लगता है। हालाँकि मुझे एक बेहतर तरीका नहीं मिला क्योंकि floatमुख्य फ़ंक्शन में कॉल करना और भी बदतर है।


61
आपका वर्तमान समाधान क्या है? यह छोटा, तेज और पठनीय है।
कर्नल पैनिक

5
और आपको सिर्फ True या False नहीं करना है। आप बदले में उपयुक्त रूप से संशोधित मूल्य वापस कर सकते हैं - उदाहरण के लिए आप इसका उपयोग उद्धरणों में गैर-संख्या डालने के लिए कर सकते हैं।
थ्रस्टन

7
एक सफल रूपांतरण के मामले में फ्लोट (ओं) के परिणाम को वापस करना बेहतर नहीं होगा? आपके पास अभी भी सफलता के लिए जांच है (परिणाम गलत है) और आप वास्तव में रूपांतरण है, जो आप वैसे भी चाहते हैं।
जूलियन

8
हालांकि यह प्रश्न अधिक पुराना है, मैं सिर्फ यह कहना चाहता था कि यह एक सुंदर तरीका है जिसे ईएएफपी के रूप में प्रलेखित किया गया है । तो शायद इस तरह की समस्या का सबसे अच्छा समाधान है।
तेरहवेंकदम

7
फ्लोट (नों) के परिणाम को वापस न करें या कोई भी असफल न हो। यदि आप इसका उपयोग करते हैं, तो x = float('0.00'); if x: use_float(x);अब आपको अपने कोड में बग मिल गया है। सत्य मान ये कारण हैं कि ये कार्य Noneपहली जगह पर लौटने के बजाय एक अपवाद को बढ़ाते हैं । एक बेहतर समाधान सिर्फ उपयोगिता फ़ंक्शन से बचने के लिए है और try catchजब आप इसका उपयोग करना चाहते हैं तो फ्लोट पर कॉल को घेर लें।
ओवंगल

जवाबों:


698

जो न केवल बदसूरत और धीमा है

मैं दोनों का विवाद करूंगा।

एक रेगेक्स या अन्य स्ट्रिंग पार्सिंग विधि बदसूरत और धीमी होगी।

मुझे यकीन नहीं है कि कुछ भी ऊपर से तेज हो सकता है। यह फ़ंक्शन को कॉल करता है और रिटर्न करता है। ट्राई / कैच ज्यादा ओवरहेड का परिचय नहीं देता है क्योंकि स्टैक फ्रेम की व्यापक खोज के बिना सबसे आम अपवाद पकड़ा गया है।

मुद्दा यह है कि किसी भी संख्यात्मक रूपांतरण फ़ंक्शन के दो प्रकार के परिणाम होते हैं

  • एक संख्या, यदि संख्या मान्य है
  • एक स्थिति कोड (उदाहरण के लिए, ग़लती से) या यह दिखाने के लिए कि कोई मान्य संख्या पार्स नहीं की जा सकती।

सी (एक उदाहरण के रूप में) इस तरीके के आसपास हैक करता है। अजगर इसे स्पष्ट रूप से और स्पष्ट रूप से देता है।

मुझे लगता है कि ऐसा करने के लिए आपका कोड एकदम सही है।


21
मुझे नहीं लगता है कि कोड सही है (लेकिन मुझे लगता है कि यह बहुत करीब है): खंड में केवल "परीक्षण" किया जा रहा हिस्सा डालना अधिक सामान्य है try, इसलिए मैं return Trueएक elseखंड में रखूंगा try। कारणों में से एक यह है कि प्रश्न में कोड के साथ, अगर मुझे इसकी समीक्षा करनी है, तो मुझे यह जांचना होगा कि tryक्लॉज में दूसरा स्टेटमेंट एक ValueRrror नहीं बढ़ा सकता है: दी गई, इसके लिए बहुत अधिक समय या मस्तिष्क की शक्ति की आवश्यकता नहीं है, लेकिन जब किसी की आवश्यकता नहीं है तो किसी का उपयोग क्यों करें?
एरिक ओ लेबिगॉट

4
जवाब सम्मोहक लगता है, लेकिन मुझे आश्चर्य होता है कि इसे आउट-ऑफ-द-बॉक्स क्यों नहीं प्रदान किया गया है ... मैं इसे कॉपी करूंगा और किसी भी मामले में इसका उपयोग करूंगा।
ऋषि

9
इतना भयानक। कैसे के बारे में अगर मुझे परवाह नहीं है कि संख्या क्या है बस यह एक संख्या है (जो मुझे यहाँ लाया है)? 1-लाइन के बजाय IsNumeric()मैं या तो एक कोशिश / कैच के साथ समाप्त होता हूं या एक अन्य कोशिश / कैच को लपेटता हूं। ऊग
मूल

6
यह 'बॉक्स से बाहर' प्रदान नहीं किया गया है क्योंकि if is_number(s): x = float(x) else: // failकोड की समान संख्या है try: x = float(x) catch TypeError: # fail। यह उपयोगिता फ़ंक्शन एक पूरी तरह से आवश्यक अमूर्तता है।
ओवंगल

12
लेकिन अमूर्तता पुस्तकालयों का पूरा बिंदु है। एक 'isNumber' फ़ंक्शन (किसी भी भाषा में) होने से एक बड़ी राशि प्राप्त करने में मदद मिलती है क्योंकि आप इसे सीधे स्टेटमेंट में बना सकते हैं और इसमें बहुत अधिक पठनीय और रख-रखाव कोड होते हैं जो कोशिश करने वाले ब्लॉक को पकड़ते हैं। इसके अलावा, यदि आपको एक से अधिक वर्ग / मॉड्यूल में एक से अधिक बार कोड का उपयोग करने की आवश्यकता है, तो आपने एक निर्मित फ़ंक्शन की तुलना में कोड की अधिक पंक्तियों का उपयोग किया होगा।
जॅम्फुल्फर

1611

यदि आप फ़्लोट्स के बजाय पार्सिंग (सकारात्मक, अहस्ताक्षरित) पूर्णांक ढूंढ रहे हैं, तो आप isdigit()स्ट्रिंग ऑब्जेक्ट्स के लिए फ़ंक्शन का उपयोग कर सकते हैं ।

>>> a = "03523"
>>> a.isdigit()
True
>>> b = "963spam"
>>> b.isdigit()
False

स्ट्रिंग के तरीके - isdigit(): पायथन 2 , पायथन 3

यूनिकोड स्ट्रिंग्स पर भी कुछ है, जिसे मैं यूनिकोड से परिचित नहीं हूँ - क्या दशमलव / दशमलव है


232
यह भी नकारात्मक पर एक नकारात्मक है
intrepion

22
घातांक के साथ भी विफल: '1e3'.isdigit () -> गलत
ssc

35
जबकि संख्या! = अंक, वे लोग जो परीक्षण करने के तरीकों की तलाश कर रहे हैं यदि एक स्ट्रिंग में एक पूर्णांक होता है, तो इस प्रश्न पर बहुत अच्छी तरह से ठोकर खा सकता है, और isDigit दृष्टिकोण बहुत अच्छी तरह से उनके आवेदन के लिए उपयुक्त हो सकता है।
एडम पार्किन

8
@AdamParkin: isdigit()और int()क्या यूनिकोड वर्ण के लिए, एक पूर्णांक जैसे है के बारे में अलग राय u'\u00b9': u'¹'.isdigit()है Trueलेकिन int(u'¹')ValueError को जन्म देती है।
jfs

6
+1: isdigit () वह नहीं हो सकता है जो ओपी देख रहा था, लेकिन यह वही है जो मैं चाहता था। यह मामला नहीं हो सकता है कि यह उत्तर और विधि सभी प्रकार की संख्याओं को कवर नहीं करती है, लेकिन यह अभी भी अत्यधिक प्रासंगिक है, इसकी सटीकता के बारे में तर्कों के विपरीत है। जबकि "संख्या! = अंक," अंक अभी भी संख्या का एक सबसेट है, विशेष रूप से संख्या जो सकारात्मक, गैर-नकारात्मक हैं, और आधार 1-10 का उपयोग करते हैं। इसके अलावा, यह विधि उन मामलों के लिए विशेष रूप से उपयोगी और संक्षिप्त है, जहां आप निरीक्षण करना चाहते हैं कि क्या एक स्ट्रिंग एक संख्यात्मक आईडी है या नहीं, जो अक्सर उन संख्याओं के सबसेट में आती है जिन्हें मैंने अभी वर्णित किया है।
जस्टिन जॉनसन

159

टीएल; डीआर सबसे अच्छा समाधान हैs.replace('.','',1).isdigit()

मैंने अलग-अलग दृष्टिकोणों की तुलना करते हुए कुछ बेंचमार्क किए

def is_number_tryexcept(s):
    """ Returns True is string is a number. """
    try:
        float(s)
        return True
    except ValueError:
        return False

import re    
def is_number_regex(s):
    """ Returns True is string is a number. """
    if re.match("^\d+?\.\d+?$", s) is None:
        return s.isdigit()
    return True


def is_number_repl_isdigit(s):
    """ Returns True is string is a number. """
    return s.replace('.','',1).isdigit()

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

funcs = [
          is_number_tryexcept, 
          is_number_regex,
          is_number_repl_isdigit
          ]

a_float = '.1234'

print('Float notation ".1234" is not supported by:')
for f in funcs:
    if not f(a_float):
        print('\t -', f.__name__)

फ्लोट नोटेशन ".1234" द्वारा समर्थित नहीं है:
- is_number_regex

scientific1 = '1.000000e+50'
scientific2 = '1e50'


print('Scientific notation "1.000000e+50" is not supported by:')
for f in funcs:
    if not f(scientific1):
        print('\t -', f.__name__)




print('Scientific notation "1e50" is not supported by:')
for f in funcs:
    if not f(scientific2):
        print('\t -', f.__name__)

वैज्ञानिक संकेतन "1.000000e + 50" द्वारा समर्थित नहीं है:
- is_number_regex
- is_number_repl_isdigit
वैज्ञानिक संकेतन "1e50" द्वारा समर्थित नहीं है:
- is_number_regex
- is_number_repl_isdigit

संपादित करें: बेंचमार्क परिणाम

import timeit

test_cases = ['1.12345', '1.12.345', 'abc12345', '12345']
times_n = {f.__name__:[] for f in funcs}

for t in test_cases:
    for f in funcs:
        f = f.__name__
        times_n[f].append(min(timeit.Timer('%s(t)' %f, 
                      'from __main__ import %s, t' %f)
                              .repeat(repeat=3, number=1000000)))

जहाँ निम्नलिखित कार्यों का परीक्षण किया गया था

from re import match as re_match
from re import compile as re_compile

def is_number_tryexcept(s):
    """ Returns True is string is a number. """
    try:
        float(s)
        return True
    except ValueError:
        return False

def is_number_regex(s):
    """ Returns True is string is a number. """
    if re_match("^\d+?\.\d+?$", s) is None:
        return s.isdigit()
    return True


comp = re_compile("^\d+?\.\d+?$")    

def compiled_regex(s):
    """ Returns True is string is a number. """
    if comp.match(s) is None:
        return s.isdigit()
    return True


def is_number_repl_isdigit(s):
    """ Returns True is string is a number. """
    return s.replace('.','',1).isdigit()

यहां छवि विवरण दर्ज करें


14
अच्छे चार्ट के लिए +1। मैंने बेंचमार्क देखा और ग्राफ देखा, सभी टीएल; डीआर बात स्पष्ट और सहज हो गई।
jcchuks

मैं @JCChuks से सहमत हूं: ग्राफ सभी TL को प्राप्त करने में बहुत मदद करता है, DR जल्दी। लेकिन मुझे लगता है कि एक टीएल? डीआर (जैसे: टीएल; डीआर : सबसे अच्छा समाधान है s.replace('.','',1).isdigit()) इस एवर की शुरुआत में दिखाई देना चाहिए। किसी भी मामले में इसे स्वीकार किया जाना चाहिए। धन्यवाद!
साइमन सी।

10
यह विधि नकारात्मक संख्या (डैश) को संभालती नहीं है। मैं सिर्फ फ्लोट पद्धति का उपयोग करने की वकालत करूंगा क्योंकि यह गलतियों की कम संभावना है और हर बार काम करेगा।
अर्चिन

3
ध्यान देने योग्य बात यह है कि धारणा पर भी पानी का छींटा नहीं पड़ सकता है, प्रतिस्थापित-isdigit विधि केवल गैर-संख्याओं (गलत परिणाम) के लिए तेज़ है, जबकि संख्याओं के लिए प्रयास-अपवाद विधि तेज़ है (सही परिणाम)। यदि आपका अधिकांश इनपुट वैध है, तो आप ट्राई-सिवाय समाधान के साथ बेहतर हैं!
मार्कस वॉन ब्रोडी

1
जैसे '1.5e-9'या नकारात्मक पर घातीय संकेतन पर काम नहीं करता है ।
EL_DON

68

एक अपवाद है जिसे आप ध्यान में रखना चाहते हैं: स्ट्रिंग 'NaN'

यदि आप चाहते हैं कि 'NaN' के लिए FALSE को वापस लेना is_number है तो यह कोड काम नहीं करेगा क्योंकि पायथन इसे एक संख्या के प्रतिनिधित्व के लिए परिवर्तित करता है जो कि संख्या नहीं है (पहचान के मुद्दों के बारे में बात करें):

>>> float('NaN')
nan

अन्यथा, मुझे वास्तव में कोड के टुकड़े के लिए धन्यवाद करना चाहिए जो अब मैं बड़े पैमाने पर उपयोग करता हूं। :)

जी


2
वास्तव में, यदि पाठ पास किया गया है तो वास्तव में एक संख्या का प्रतिनिधित्व NaNकरने के लिए वापस जाने के बजाय (बजाय False) एक अच्छा मूल्य हो सकता है । इसके लिए जाँच करना एक दर्द की तरह है (पायथन के floatप्रकार को वास्तव में इसके लिए एक विधि की आवश्यकता है) लेकिन आप इसे बिना किसी त्रुटि के उत्पादन के लिए गणना में उपयोग कर सकते हैं, और केवल परिणाम की जांच करने की आवश्यकता है।
थोड़े

7
एक और अपवाद स्ट्रिंग है 'inf'। या तो infया NaNभी एक साथ उपसर्ग किया जा सकता है +या -और अभी भी स्वीकार किया।
'23

4
यदि आप NaN और Inf के लिए गलत लौटना चाहते हैं, तो लाइन को x = float (s) में बदलें; वापसी (x == x) और (x - 1! = x)। यह Inf और NaN
RyanN

5
x-1 == xसे बड़ी फ्लोट्स के लिए सच है inf। पायथन 3.2 से आप उन math.isfiniteनंबरों के परीक्षण के लिए उपयोग कर सकते हैं जो न तो NaN हैं और न ही अनंत, या दोनों की जांच करें math.isnanऔर उससे math.isinfपहले।
स्टीव जेसप

56

इस बारे में कैसा है:

'3.14'.replace('.','',1).isdigit()

जो एक या एक नहीं है, तो ही सही। ' अंकों की स्ट्रिंग में।

'3.14.5'.replace('.','',1).isdigit()

झूठा लौटेगा

संपादित करें: बस एक और टिप्पणी देखी ... .replace(badstuff,'',maxnum_badstuff)अन्य मामलों के लिए जोड़ दिया जा सकता है। यदि आप नमक पास कर रहे हैं और मनमाना मसाला नहीं है (Ref: xkcd # 974 ) तो यह ठीक हो जाएगा: P


7
हालांकि यह नकारात्मक संख्या के लिए जिम्मेदार नहीं है।
माइकल बार्टन

5
या 1.234e56( जैसे +1.234E+56और भी कई वेरिएंट के रूप में भी लिखा जा सकता है) जैसे घातांक के साथ संख्या ।
अल्फ

re.match(r'^[+-]*(0[xbo])?[0-9A-Fa-f]*\.?[0-9A-Fa-f]*(E[+-]*[0-9A-Fa-f]+)$', 'str')एक संख्या निर्धारित करने का एक बेहतर काम करना चाहिए (लेकिन सभी नहीं, मैं यह दावा नहीं कर रहा हूं)। मैं इसका उपयोग करने की सलाह नहीं देता, प्रश्नकर्ता के मूल कोड का उपयोग करने के लिए बेहतर है।
बाल्ड्रिक

यदि आप इस समाधान को पसंद नहीं करते हैं, तो इसे डाउनवॉट करने से पहले पढ़ें!
aloisdg codidact.com

आदमी यह सबसे चतुर समाधान है जो मैंने कभी इस वेबसाइट में देखा है!
करम क़ुसाई

41

जो न केवल बदसूरत और धीमा है, बल्कि भद्दा लगता है।

यह कुछ करने के लिए इस्तेमाल किया जा सकता है, लेकिन यह इसे करने का pythonic तरीका है। जैसा कि पहले ही बताया जा चुका है, विकल्प बदतर हैं। लेकिन इस तरह से काम करने का एक और फायदा है: बहुरूपता।

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

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

एक और चीज जिसे आप ध्यान में रखना चाहते हैं: पायथन बहुत अधिक अन्य भाषाओं की तुलना में अपवादों को फेंकने और पकड़ने में बहुत तेज है (उदाहरण के लिए .Net की तुलना में तेजी से 30x)। हेक, गैर-असाधारण, सामान्य कार्यक्रम स्थितियों (हर बार जब आप लूप के लिए उपयोग करते हैं) संवाद करने के लिए भाषा स्वयं भी अपवादों को फेंकती है। इस प्रकार, मुझे इस कोड के प्रदर्शन पहलुओं के बारे में बहुत चिंता नहीं होगी जब तक कि आप एक महत्वपूर्ण समस्या को नोटिस नहीं करते।


1
एक और आम जगह जहां पायथन बुनियादी कार्यों के लिए अपवादों का उपयोग करता है, hasattr()जिसमें सिर्फ एक getattr()कॉल लपेटा जाता है try/except। फिर भी, सामान्य प्रवाह नियंत्रण की तुलना में अपवाद को संभालना धीमा है, इसलिए इसे किसी ऐसी चीज के लिए उपयोग करना जो सच हो जाए , इसका परिणाम प्रदर्शन जुर्माना हो सकता है।
थोड़े

ऐसा लगता है कि अगर आप एक-लाइनर चाहते हैं, तो आप SOL
बेसिक

इसके अलावा पाइथोनिक यह विचार है कि यह "अनुमति से माफी मांगने के लिए बेहतर है", सस्ते अपवाद होने के प्रभाव के बारे में।
हेल्टनबिकर

40

Alfe के बाद अपडेट किया गया है कि आपको फ्लोट के लिए अलग से जांच करने की आवश्यकता नहीं है क्योंकि दोनों जटिल हैंडल के रूप में हैं:

def is_number(s):
    try:
        complex(s) # for int, long, float and complex
    except ValueError:
        return False

    return True

पहले कहा गया था: क्या कुछ दुर्लभ मामलों में आपको जटिल संख्या (जैसे 1 + 2i) की जांच करनी पड़ सकती है, जिसे फ्लोट द्वारा दर्शाया नहीं जा सकता है:

def is_number(s):
    try:
        float(s) # for int, long and float
    except ValueError:
        try:
            complex(s) # for complex
        except ValueError:
            return False

    return True

14
मैं असहमत हूं। यह सामान्य उपयोग में संभावना नहीं है, और आप बेहतर तरीके से एक is_complex_number () कॉल का उपयोग कर रहे हैं, जब आप उनका उपयोग कर रहे हैं, बजाय एक ऑपरेशन के अतिरिक्त 0.0001% दुस्साहस की संभावना के लिए कॉल के बोझ के साथ।
जूलियन

3
आप float()पूरी तरह से सामान को छीन सकते हैं और बस complex()सफल होने के लिए कॉल की जांच कर सकते हैं । सब कुछ के द्वारा पार्स किया float()जा सकता है complex()
अल्फ

यह फ़ंक्शन पंडों के NaN और Inf मानों को संख्यात्मक मानों के रूप में लौटाएगा।
फिक्सकियर

complex('(01989)')वापस आ जाएगा (1989+0j)। लेकिन float('(01989)')असफल हो जाएगा। इसलिए मुझे लगता है कि प्रयोग complexकरना अच्छा विचार नहीं है।
plhn

26

इसके intउपयोग के लिए :

>>> "1221323".isdigit()
True

लेकिन floatहमें कुछ ट्रिक्स की जरूरत है ;-)। हर फ्लोट नंबर में एक बिंदु होता है ...

>>> "12.34".isdigit()
False
>>> "12.34".replace('.','',1).isdigit()
True
>>> "12.3.4".replace('.','',1).isdigit()
False

इसके अलावा नकारात्मक संख्याओं के लिए lstrip():

>>> '-12'.lstrip('-')
'12'

और अब हम एक सार्वभौमिक तरीका प्राप्त करते हैं:

>>> '-12.34'.lstrip('-').replace('.','',1).isdigit()
True
>>> '.-234'.lstrip('-').replace('.','',1).isdigit()
False

2
जैसी चीजों को संभालना पसंद नहीं करता है 1.234e56। इसके अलावा, मुझे दिलचस्पी होगी कि आप कैसे पता लगाएंगे कि 99999999999999999999e99999999999999999999यह संख्या नहीं है। पार्स करने की कोशिश करने से यह जल्दी पता चल जाता है।
अल्फ

यह 50 मीटर स्ट्रिंग्स की सूची में स्वीकृत समाधान की तुलना में ~ 30% तेज और 5k स्ट्रिंग्स की सूची में 150% तेजी से चलता है। A
ज़ेव एवेरबैच

15

जस्ट मिमिक C #

C # में दो अलग-अलग कार्य हैं जो स्केलर मानों के पार्सिंग को संभालते हैं:

  • Float.Parse ()
  • Float.TryParse ()

float.parse ():

def parse(string):
    try:
        return float(string)
    except Exception:
        throw TypeError

नोट: यदि आप सोच रहे हैं कि मैंने अपवाद को TypeError में क्यों बदल दिया, तो यहाँ प्रलेखन है

float.try_parse ():

def try_parse(string, fail=None):
    try:
        return float(string)
    except Exception:
        return fail;

नोट: आप बूलियन 'गलत' वापस नहीं करना चाहते क्योंकि यह अभी भी एक मूल्य प्रकार है। कोई भी बेहतर नहीं है क्योंकि यह विफलता को इंगित करता है। बेशक, यदि आप कुछ अलग करना चाहते हैं तो आप असफल पैरामीटर को जो कुछ भी चाहते हैं उसे बदल सकते हैं।

'पार्स ()' और 'ट्राइ_पर्स ()' को शामिल करने के लिए फ्लोट का विस्तार करने के लिए आपको इन तरीकों को जोड़ने के लिए 'फ्लोट' क्लास को बंद करने की आवश्यकता होगी।

यदि आप चाहते हैं कि सम्मान पूर्व-मौजूदा कार्यों के लिए कोड कुछ इस तरह होना चाहिए:

def monkey_patch():
    if(!hasattr(float, 'parse')):
        float.parse = parse
    if(!hasattr(float, 'try_parse')):
        float.try_parse = try_parse

साइडनोट: मैं व्यक्तिगत रूप से इसे मंकी पंचिंग कहना पसंद करता हूं क्योंकि ऐसा लगता है कि जब मैं ऐसा करता हूं तो मैं भाषा का दुरुपयोग कर रहा हूं लेकिन वाईएमएमवी।

उपयोग:

float.parse('giggity') // throws TypeException
float.parse('54.3') // returns the scalar value 54.3
float.tryParse('twank') // returns None
float.tryParse('32.2') // returns the scalar value 32.2

और महान ऋषि पायथनस ने पवित्र देख शार्पिस से कहा, "आप जो कुछ भी कर सकते हैं वह मैं बेहतर कर सकता हूं; मैं आपसे बेहतर कुछ भी कर सकता हूं।"


मैं ज्यादातर जेएस में हाल ही में कोडिंग कर रहा हूं और वास्तव में इसका परीक्षण नहीं किया है इसलिए कुछ छोटी त्रुटियां हो सकती हैं। यदि आप कोई भी देखते हैं, तो मेरी गलतियों को सुधारने के लिए स्वतंत्र महसूस करें।
इवान प्लाइस

जटिल संख्याओं के लिए समर्थन जोड़ने के लिए @Matthew Wilcoxson द्वारा उत्तर देखें। stackoverflow.com/a/3335060/290340
इवान प्लाइस

1
के !बजाय का उपयोग करना notएक छोटी सी त्रुटि हो सकती है, लेकिन आप निश्चित रूप से अंतर्निहित floatCPython में विशेषताओं को निर्दिष्ट नहीं कर सकते ।
ब्लेक जेक

15

गैर-संख्याओं के तार के लिए, try: except:वास्तव में नियमित अभिव्यक्तियों की तुलना में धीमी है। मान्य संख्याओं के तार के लिए, रेगेक्स धीमा है। तो, उपयुक्त विधि आपके इनपुट पर निर्भर करती है।

आप पाते हैं कि आप एक प्रदर्शन बाँध में हैं, तो आप एक नया तीसरे पक्ष के मॉड्यूल बुलाया का उपयोग कर सकते fastnumbers एक समारोह कहा जाता है प्रदान करता है कि isfloat । पूर्ण प्रकटीकरण, मैं लेखक हूँ। मैंने इसके परिणामों को नीचे दिए गए समय में शामिल किया है।


from __future__ import print_function
import timeit

prep_base = '''\
x = 'invalid'
y = '5402'
z = '4.754e3'
'''

prep_try_method = '''\
def is_number_try(val):
    try:
        float(val)
        return True
    except ValueError:
        return False

'''

prep_re_method = '''\
import re
float_match = re.compile(r'[-+]?\d*\.?\d+(?:[eE][-+]?\d+)?$').match
def is_number_re(val):
    return bool(float_match(val))

'''

fn_method = '''\
from fastnumbers import isfloat

'''

print('Try with non-number strings', timeit.timeit('is_number_try(x)',
    prep_base + prep_try_method), 'seconds')
print('Try with integer strings', timeit.timeit('is_number_try(y)',
    prep_base + prep_try_method), 'seconds')
print('Try with float strings', timeit.timeit('is_number_try(z)',
    prep_base + prep_try_method), 'seconds')
print()
print('Regex with non-number strings', timeit.timeit('is_number_re(x)',
    prep_base + prep_re_method), 'seconds')
print('Regex with integer strings', timeit.timeit('is_number_re(y)',
    prep_base + prep_re_method), 'seconds')
print('Regex with float strings', timeit.timeit('is_number_re(z)',
    prep_base + prep_re_method), 'seconds')
print()
print('fastnumbers with non-number strings', timeit.timeit('isfloat(x)',
    prep_base + 'from fastnumbers import isfloat'), 'seconds')
print('fastnumbers with integer strings', timeit.timeit('isfloat(y)',
    prep_base + 'from fastnumbers import isfloat'), 'seconds')
print('fastnumbers with float strings', timeit.timeit('isfloat(z)',
    prep_base + 'from fastnumbers import isfloat'), 'seconds')
print()

Try with non-number strings 2.39108395576 seconds
Try with integer strings 0.375686168671 seconds
Try with float strings 0.369210958481 seconds

Regex with non-number strings 0.748660802841 seconds
Regex with integer strings 1.02021503448 seconds
Regex with float strings 1.08564686775 seconds

fastnumbers with non-number strings 0.174362897873 seconds
fastnumbers with integer strings 0.179651021957 seconds
fastnumbers with float strings 0.20222902298 seconds

जैसा कि आप देख सकते हैं

  • try: except: संख्यात्मक इनपुट के लिए तेज़ था लेकिन अमान्य इनपुट के लिए बहुत धीमा था
  • इनपुट अमान्य होने पर regex बहुत कुशल है
  • fastnumbers दोनों ही मामलों में जीत

मैं सही खड़ा हूँ: -} यह सिर्फ ऐसा नहीं लग रहा था जैसे यह कर रहा था। शायद जैसे नामों का उपयोग कर रहा होगा prep_code_basisऔर prep_code_re_methodमेरी गलती को रोका होगा।
अल्फ

क्या आप बता रहे हैं कि आपका मॉड्यूल कैसे काम करता है, कम से कम isfloatफ़ंक्शन के लिए?
सुलैमान ऊको

@SolomonUcko यहां स्ट्रिंग चेकिंग पार्ट के लिए सोर्स कोड का लिंक दिया गया है: github.com/SethMMorton/fastnumbers/blob/v1.0.0/src/… । मूल रूप से, यह क्रम में स्ट्रिंग में प्रत्येक वर्ण पर चलता है और यह पुष्टि करता है कि यह एक वैध फ्लोट के लिए एक पैटर्न का अनुसरण करता है। यदि इनपुट पहले से ही एक संख्या है, तो यह केवल तेज PyFloat_Check का उपयोग करता है ।
सेठमोर्टन

1
इस थ्रेड में सबसे अच्छे विकल्पों के खिलाफ परीक्षण किया गया है मैं पुष्टि करता हूं कि यह समाधान अब तक का सबसे तेज है। दूसरी सबसे तेज़ विधि str(s).strip('-').replace('.','',1).isdigit()जो लगभग 10x धीमी है!
अलेक्जेंडर मैकफारलेन

14

मुझे पता है कि यह विशेष रूप से पुराना है, लेकिन मैं एक जवाब जोड़ूंगा जो मुझे लगता है कि सबसे अधिक मतदान वाले उत्तर से गायब जानकारी को कवर करता है जो किसी भी व्यक्ति के लिए बहुत मूल्यवान हो सकता है:

निम्न विधियों में से प्रत्येक के लिए उन्हें एक गिनती के साथ कनेक्ट करें यदि आपको किसी इनपुट की आवश्यकता है तो उसे स्वीकार किया जाना चाहिए। (यह मानकर कि हम पूर्णांक 0-25 के बजाय पूर्णांक की मुखर परिभाषा का उपयोग कर रहे हैं, आदि)

x.isdigit() अगर x एक पूर्णांक है, तो जाँच के लिए अच्छी तरह से काम करता है।

x.replace('-','').isdigit() जाँच करने के लिए अच्छी तरह से काम करता है अगर x एक नकारात्मक है। (जाँच करें - पहली स्थिति में)

x.replace('.','').isdigit() जाँच करने के लिए अच्छी तरह से काम करता है अगर x एक दशमलव है।

x.replace(':','').isdigit() जाँच करने के लिए अच्छी तरह से काम करता है अगर x एक अनुपात है।

x.replace('/','',1).isdigit() जाँच करने के लिए अच्छी तरह से काम करता है अगर x एक अंश है।


1
हालांकि अंशों के लिए, आपको शायद करने की आवश्यकता है x.replace('/','',1).isdigit()या अन्यथा दिनांक 4/7/2017 जैसे कि संख्या के रूप में गलत व्याख्या की जाएगी।
युकुआन चेन

स्थितियों को श्रृंखलाबद्ध करने के सर्वोत्तम तरीकों के लिए: stackoverflow.com/q/3411771/5922329
डैनियल ब्रौन

13

यह उत्तर स्टेप गाइड द्वारा चरण प्रदान करता है जिसमें स्ट्रिंग को खोजने के लिए उदाहरण के साथ फ़ंक्शन होता है:

  • सकारात्मक पूर्णांक
  • धनात्मक / ऋणात्मक - पूर्णांक / फ्लोट
  • संख्या की जाँच करते समय "NaN" (संख्या नहीं) तार कैसे छोड़ें?

जांचें कि क्या स्ट्रिंग धनात्मक पूर्णांक है

आप यह str.isdigit()जांचने के लिए उपयोग कर सकते हैं कि दिया गया तार धनात्मक पूर्णांक है या नहीं।

नमूना परिणाम:

# For digit
>>> '1'.isdigit()
True
>>> '1'.isalpha()
False

धनात्मक / ऋणात्मक - पूर्णांक / फ्लोट के रूप में स्ट्रिंग की जाँच करें

str.isdigit()रिटर्न Falseअगर स्ट्रिंग एक नकारात्मक संख्या या एक फ्लोट संख्या है। उदाहरण के लिए:

# returns `False` for float
>>> '123.3'.isdigit()
False
# returns `False` for negative number
>>> '-123'.isdigit()
False

यदि आप भी नकारात्मक पूर्णांक के लिए जाँचfloat करना चाहते हैं और , तो आप एक कस्टम फ़ंक्शन को इसके लिए जाँच सकते हैं:

def is_number(n):
    try:
        float(n)   # Type-casting the string to `float`.
                   # If string is not a valid `float`, 
                   # it'll raise `ValueError` exception
    except ValueError:
        return False
    return True

नमूना रन:

>>> is_number('123')    # positive integer number
True

>>> is_number('123.4')  # positive float number
True

>>> is_number('-123')   # negative integer number
True

>>> is_number('-123.4') # negative `float` number
True

>>> is_number('abc')    # `False` for "some random" string
False

संख्या के लिए जाँच करते समय "NaN" (संख्या नहीं) तार छोड़ें

उपरोक्त फ़ंक्शन True"NAN" (संख्या नहीं) स्ट्रिंग के लिए वापस आ जाएगा क्योंकि पायथन के लिए यह मान्य फ्लोट है यह दर्शाता है कि यह संख्या नहीं है। उदाहरण के लिए:

>>> is_number('NaN')
True

यह जांचने के लिए कि क्या नंबर "NaN" है, आप निम्नानुसार उपयोग कर सकते हैं math.isnan():

>>> import math
>>> nan_num = float('nan')

>>> math.isnan(nan_num)
True

या यदि आप इसे जांचने के लिए अतिरिक्त लाइब्रेरी आयात नहीं करना चाहते हैं, तो आप बस इसे स्वयं के साथ तुलना करके जांच सकते हैं ==Falseजब nanफ्लोट की तुलना खुद से की जाती है तो पायथन लौटता है। उदाहरण के लिए:

# `nan_num` variable is taken from above example
>>> nan_num == nan_num
False

इसलिए, उपरोक्त फ़ंक्शन को is_numberनिम्न पर लौटने के Falseलिए अपडेट किया जा सकता है"NaN" :

def is_number(n):
    is_number = True
    try:
        num = float(n)
        # check for "nan" floats
        is_number = num == num   # or use `math.isnan(num)`
    except ValueError:
        is_number = False
    return is_number

नमूना रन:

>>> is_number('Nan')   # not a number "Nan" string
False

>>> is_number('nan')   # not a number string "nan" with all lower cased
False

>>> is_number('123')   # positive integer
True

>>> is_number('-123')  # negative integer
True

>>> is_number('-1.12') # negative `float`
True

>>> is_number('abc')   # "some random" string
False

पुनश्च: संख्या के प्रकार के आधार पर प्रत्येक चेक के लिए प्रत्येक ऑपरेशन अतिरिक्त ओवरहेड के साथ आता है। is_numberफ़ंक्शन का संस्करण चुनें जो आपकी आवश्यकता पर फिट बैठता है।


12

फ्लोट करने के लिए कास्टिंग करना और ValueError को पकड़ना शायद सबसे तेज़ तरीका है, क्योंकि फ़्लोट () विशेष रूप से बस के लिए है। कुछ भी जिसके लिए स्ट्रिंग पार्सिंग (regex, आदि) की आवश्यकता होती है, इस तथ्य के कारण धीमी हो जाएगी कि यह इस ऑपरेशन के लिए तैयार नहीं है। मेरी $ 0.02।


11
आपका "2e-2" डॉलर एक फ्लोट भी है (फ्लोट का उपयोग करने के लिए एक अतिरिक्त तर्क :)
tzot

8
मौद्रिक मूल्य का प्रतिनिधित्व करने के लिए @ फ्लोट का उपयोग न करें।
ल्यूक

6
@ ल्यूक: मैं पूरी तरह से आपके साथ सहमत हूं, हालांकि मैंने कभी मौद्रिक मूल्यों का प्रतिनिधित्व करने के लिए फ़्लोट्स का उपयोग करने का सुझाव नहीं दिया; मैंने सिर्फ इतना कहा कि मौद्रिक मूल्यों को फ़्लोट्स के रूप में दर्शाया जा सकता है :)
tzot

11

आप यूनिकोड स्ट्रिंग्स का उपयोग कर सकते हैं, उनके पास वह तरीका है जो आप चाहते हैं:

>>> s = u"345"
>>> s.isnumeric()
True

या:

>>> s = "345"
>>> u = unicode(s)
>>> u.isnumeric()
True

http://www.tutorialspoint.com/python/string_isnumeric.htm

http://docs.python.org/2/howto/unicode.html


2
गैर-नकारात्मक ints के लिए यह ठीक है; ;-)
andilabs

1
s.isdecimal()जाँचता है कि sस्ट्रिंग एक गैर-नकारात्मक पूर्णांक है। s.isnumeric()ऐसे वर्ण शामिल हैं जो int()अस्वीकार करते हैं।
JFS

9

मैं देखना चाहता था कि कौन सी विधि सबसे तेज़ है। कुल मिलाकर सबसे अच्छा और सबसे लगातार परिणाम check_replaceसमारोह द्वारा दिए गए थे । सबसे तेज़ परिणाम check_exceptionफ़ंक्शन द्वारा दिए गए थे , लेकिन केवल अगर कोई अपवाद नहीं निकाल दिया गया था - जिसका अर्थ है कि इसका कोड सबसे कुशल है, लेकिन अपवाद फेंकने का ओवरहेड काफी बड़ा है।

कृपया ध्यान दें कि एक सफल कलाकार के लिए जाँच करना एकमात्र तरीका है जो सटीक है, उदाहरण के लिए, यह काम करता है check_exceptionलेकिन अन्य दो परीक्षण कार्य एक वैध फ्लोट के लिए गलत लौटा देंगे:

huge_number = float('1e+100')

यहाँ बेंचमार्क कोड है:

import time, re, random, string

ITERATIONS = 10000000

class Timer:    
    def __enter__(self):
        self.start = time.clock()
        return self
    def __exit__(self, *args):
        self.end = time.clock()
        self.interval = self.end - self.start

def check_regexp(x):
    return re.compile("^\d*\.?\d*$").match(x) is not None

def check_replace(x):
    return x.replace('.','',1).isdigit()

def check_exception(s):
    try:
        float(s)
        return True
    except ValueError:
        return False

to_check = [check_regexp, check_replace, check_exception]

print('preparing data...')
good_numbers = [
    str(random.random() / random.random()) 
    for x in range(ITERATIONS)]

bad_numbers = ['.' + x for x in good_numbers]

strings = [
    ''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(random.randint(1,10)))
    for x in range(ITERATIONS)]

print('running test...')
for func in to_check:
    with Timer() as t:
        for x in good_numbers:
            res = func(x)
    print('%s with good floats: %s' % (func.__name__, t.interval))
    with Timer() as t:
        for x in bad_numbers:
            res = func(x)
    print('%s with bad floats: %s' % (func.__name__, t.interval))
    with Timer() as t:
        for x in strings:
            res = func(x)
    print('%s with strings: %s' % (func.__name__, t.interval))

2017 मैकबुक प्रो 13 पर पायथन 2.7.10 के साथ परिणाम यहां दिए गए हैं:

check_regexp with good floats: 12.688639
check_regexp with bad floats: 11.624862
check_regexp with strings: 11.349414
check_replace with good floats: 4.419841
check_replace with bad floats: 4.294909
check_replace with strings: 4.086358
check_exception with good floats: 3.276668
check_exception with bad floats: 13.843092
check_exception with strings: 15.786169

2017 मैकबुक प्रो 13 पर पायथन 3.6.5 के साथ परिणाम यहां दिए गए हैं:

check_regexp with good floats: 13.472906000000009
check_regexp with bad floats: 12.977665000000016
check_regexp with strings: 12.417542999999995
check_replace with good floats: 6.011045999999993
check_replace with bad floats: 4.849356
check_replace with strings: 4.282754000000011
check_exception with good floats: 6.039081999999979
check_exception with bad floats: 9.322753000000006
check_exception with strings: 9.952595000000002

2017 मैकबुक प्रो 13 पर PyPy 2.7.13 के साथ परिणाम यहां दिए गए हैं:

check_regexp with good floats: 2.693217
check_regexp with bad floats: 2.744819
check_regexp with strings: 2.532414
check_replace with good floats: 0.604367
check_replace with bad floats: 0.538169
check_replace with strings: 0.598664
check_exception with good floats: 1.944103
check_exception with bad floats: 2.449182
check_exception with strings: 2.200056

10
आपको अमान्य मामलों के लिए प्रदर्शन का भी परीक्षण करना चाहिए। इन संख्याओं के साथ कोई अपवाद नहीं उठाया गया है, जो वास्तव में "धीमा" हिस्सा है।
Ugo Méda

1
@ UgoMéda i ने 2013 से आपकी सलाह ली और इसे किया :)
Ron Reiter

"कृपया ध्यान दें कि एक सफल कलाकार के लिए जाँच एकमात्र तरीका है जो सटीक है" <- यह वास्तव में सच नहीं है। मैंने ऊपर दिए गए मेरे उत्तर में regexp का उपयोग करके आपका परीक्षण चलाया है, और यह वास्तव में regexp की तुलना में तेज़ी से चलता है। मैं अपने उत्तर में परिणाम जोड़ दूंगा।
डेविड लजंग मैडिसन स्टेलर

संयोग से, एक मनोरंजक बिंदु के रूप में, आपके बुरे नंबर निर्माता वास्तव में कुछ कानूनी संख्याएं बना सकते हैं, हालांकि यह काफी दुर्लभ होगा। :)
डेविड लैजंग मैडिसन स्टेलर

8

तो यह सब एक साथ रखने के लिए, नेन, अनन्तता और जटिल संख्याओं के लिए जाँच (यह प्रतीत होता है कि वे जे के साथ निर्दिष्ट किए गए हैं, न कि मैं, अर्थात 1 + 2 जे) इसके परिणामस्वरूप:

def is_number(s):
    try:
        n=str(float(s))
        if n == "nan" or n=="inf" or n=="-inf" : return False
    except ValueError:
        try:
            complex(s) # for complex
        except ValueError:
            return False
    return True

अब तक का सबसे अच्छा जवाब। धन्यवाद
अनीश

6

इनपुट निम्नानुसार हो सकता है:

a="50" b=50 c=50.1 d="50.1"


1-सामान्य इनपुट:

इस फ़ंक्शन का इनपुट सब कुछ हो सकता है!

दिया गया है कि क्या दिया गया चर संख्यात्मक है। न्यूमेरिक स्ट्रिंग्स में वैकल्पिक संकेत, अंकों की कोई संख्या, वैकल्पिक दशमलव भाग और वैकल्पिक घातीय भाग शामिल होते हैं। इस प्रकार + 0123.45e6 एक मान्य संख्यात्मक मान है। हेक्साडेसिमल (जैसे 0xf4c3b00c) और बाइनरी (जैसे 0b10100111001) संकेतन की अनुमति नहीं है।

is_numeric function है

import ast
import numbers              
def is_numeric(obj):
    if isinstance(obj, numbers.Number):
        return True
    elif isinstance(obj, str):
        nodes = list(ast.walk(ast.parse(obj)))[1:]
        if not isinstance(nodes[0], ast.Expr):
            return False
        if not isinstance(nodes[-1], ast.Num):
            return False
        nodes = nodes[1:-1]
        for i in range(len(nodes)):
            #if used + or - in digit :
            if i % 2 == 0:
                if not isinstance(nodes[i], ast.UnaryOp):
                    return False
            else:
                if not isinstance(nodes[i], (ast.USub, ast.UAdd)):
                    return False
        return True
    else:
        return False

परीक्षा:

>>> is_numeric("54")
True
>>> is_numeric("54.545")
True
>>> is_numeric("0x45")
True

is_float फ़ंक्शन

दिया गया चर दिया गया है या नहीं। फ्लोट स्ट्रिंग्स में वैकल्पिक संकेत, अंकों की कोई भी संख्या शामिल होती है ...

import ast

def is_float(obj):
    if isinstance(obj, float):
        return True
    if isinstance(obj, int):
        return False
    elif isinstance(obj, str):
        nodes = list(ast.walk(ast.parse(obj)))[1:]
        if not isinstance(nodes[0], ast.Expr):
            return False
        if not isinstance(nodes[-1], ast.Num):
            return False
        if not isinstance(nodes[-1].n, float):
            return False
        nodes = nodes[1:-1]
        for i in range(len(nodes)):
            if i % 2 == 0:
                if not isinstance(nodes[i], ast.UnaryOp):
                    return False
            else:
                if not isinstance(nodes[i], (ast.USub, ast.UAdd)):
                    return False
        return True
    else:
        return False

परीक्षा:

>>> is_float("5.4")
True
>>> is_float("5")
False
>>> is_float(5)
False
>>> is_float("5")
False
>>> is_float("+5.4")
True

क्या अचरज है ?


2- यदि आप आश्वस्त हैं कि चर सामग्री स्ट्रिंग है :

str.isdigit () विधि का उपयोग करें

>>> a=454
>>> a.isdigit()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'int' object has no attribute 'isdigit'
>>> a="454"
>>> a.isdigit()
True

3-संख्यात्मक इनपुट:

int मान का पता लगाएं:

>>> isinstance("54", int)
False
>>> isinstance(54, int)
True
>>> 

नाव का पता लगाएं:

>>> isinstance("45.1", float)
False
>>> isinstance(45.1, float)
True

" ast" क्या है ?

4

मैंने कुछ गति परीक्षण किया। कहते हैं कि चलो कि अगर स्ट्रिंग है की संभावना एक संख्या होने की कोशिश / छोड़कर रणनीति सबसे तेजी से possible.If स्ट्रिंग है की संभावना नहीं कोई संख्या होना चाहिए और अपनी रुचि के अनुसार पूर्णांक जांच, यह कुछ परीक्षण (isdigit प्लस शीर्षक करने के लिए worths '-')। यदि आप फ्लोट संख्या की जांच करने के लिए इच्छुक हैं, तो आपको कोड व्हाईटआउट एस्केप को छोड़कर / कोशिश का उपयोग करना होगा ।


4

मुझे यह निर्धारित करने की आवश्यकता है कि क्या एक स्ट्रिंग मूल प्रकार (फ्लोट, इंट, स्ट्र, बूल) में डाली गई है। इंटरनेट पर कुछ भी नहीं खोजने के बाद मैंने इसे बनाया:

def str_to_type (s):
    """ Get possible cast type for a string

    Parameters
    ----------
    s : string

    Returns
    -------
    float,int,str,bool : type
        Depending on what it can be cast to

    """    
    try:                
        f = float(s)        
        if "." not in s:
            return int
        return float
    except ValueError:
        value = s.upper()
        if value == "TRUE" or value == "FALSE":
            return bool
        return type(s)

उदाहरण

str_to_type("true") # bool
str_to_type("6.0") # float
str_to_type("6") # int
str_to_type("6abc") # str
str_to_type(u"6abc") # unicode       

आप प्रकार को पकड़ सकते हैं और इसका उपयोग कर सकते हैं

s = "6.0"
type_ = str_to_type(s) # float
f = type_(s) 

3

रयान ने सुझाव दिया

यदि आप NaN और Inf के लिए गलत लौटना चाहते हैं, तो लाइन को x = float (s) में बदलें; वापसी (x == x) और (x - 1! = x)। यह Inf और NaN को छोड़कर सभी फ्लोट्स के लिए True लौटना चाहिए

लेकिन यह काफी काम नहीं करता है, क्योंकि पर्याप्त रूप से बड़ी फ़्लोट्स के लिए, x-1 == xसही है। उदाहरण के लिए,2.0**54 - 1 == 2.0**54


3

मुझे लगता है कि आपका समाधान ठीक है, लेकिन वहाँ है एक सही regexp कार्यान्वयन।

ऐसा लगता है कि इन उत्तरों के प्रति बहुत अधिक द्वेष है, जो मुझे लगता है कि अनुचित है, रेगेक्स काफी हद तक साफ और सही और तेज हो सकता है। यह वास्तव में आप क्या करने की कोशिश कर रहे हैं पर निर्भर करता है। मूल प्रश्न यह था कि आप "जाँच सकते हैं कि क्या एक स्ट्रिंग को एक संख्या (फ्लोट) के रूप में दर्शाया जा सकता है" (अपने शीर्षक के अनुसार)। निश्चित रूप से आप संख्यात्मक / फ्लोट मूल्य का उपयोग करना चाहते हैं एक बार जब आप यह जाँच लेते हैं कि यह वैध है, तो आपकी कोशिश / सिवाय इसके बहुत मायने रखती है। लेकिन अगर, किसी कारण से, आप बस उस स्ट्रिंग को मान्य करना चाहते हैं एक संख्या हैफिर एक रेगेक्स भी ठीक काम करता है, लेकिन इसे ठीक करना मुश्किल है। मुझे लगता है कि अभी तक अधिकांश रेगेक्स उत्तर हैं, उदाहरण के लिए, पूर्णांक के बिना तार को ठीक से पार्स न करें (जैसे कि ".7") जो कि एक फ्लोट है जहां तक ​​अजगर का संबंध है। और यह थोड़ा मुश्किल है कि एक एकल रेगेक्स की जांच करें जहां आंशिक भाग की आवश्यकता नहीं है। मैंने इसे दिखाने के लिए दो रेगेक्स को शामिल किया है।

यह दिलचस्प सवाल उठाता है कि "संख्या" क्या है। क्या आप "inf" को शामिल करते हैं जो कि अजगर में तैरने के रूप में मान्य है? या क्या आप ऐसे नंबर शामिल करते हैं जो "संख्या" हैं, लेकिन शायद अजगर में प्रतिनिधित्व नहीं किया जा सकता है (जैसे कि संख्या जो फ़्लोट अधिकतम से अधिक है)।

आप संख्याओं को कैसे पार्स करते हैं, इसमें अस्पष्टता भी है। उदाहरण के लिए, "- 20" के बारे में क्या? क्या यह "संख्या" है? क्या यह "20" का प्रतिनिधित्व करने का एक कानूनी तरीका है? पायथन आपको "var = - 20" करने देगा और इसे 20 पर सेट करेगा (हालांकि वास्तव में ऐसा इसलिए है क्योंकि यह इसे एक अभिव्यक्ति के रूप में मानता है), लेकिन फ्लोट ("- 20") काम नहीं करता है।

वैसे भी, अधिक जानकारी के बिना, यहाँ एक regex है जो मुझे लगता है कि सभी चींटियों को कवर करता है और अजगर अजगर के रूप में तैरते हैं

# Doesn't properly handle floats missing the integer part, such as ".7"
SIMPLE_FLOAT_REGEXP = re.compile(r'^[-+]?[0-9]+\.?[0-9]+([eE][-+]?[0-9]+)?$')
# Example "-12.34E+56"      # sign (-)
                            #     integer (12)
                            #           mantissa (34)
                            #                    exponent (E+56)

# Should handle all floats
FLOAT_REGEXP = re.compile(r'^[-+]?([0-9]+|[0-9]*\.[0-9]+)([eE][-+]?[0-9]+)?$')
# Example "-12.34E+56"      # sign (-)
                            #     integer (12)
                            #           OR
                            #             int/mantissa (12.34)
                            #                            exponent (E+56)

def is_float(str):
  return True if FLOAT_REGEXP.match(str) else False

कुछ उदाहरण परीक्षण मान:

True  <- +42
True  <- +42.42
False <- +42.42.22
True  <- +42.42e22
True  <- +42.42E-22
False <- +42.42e-22.8
True  <- .42
False <- 42nope

@ रॉन-रेइटर के उत्तर में बेंचमार्किंग कोड चलाने से पता चलता है कि यह रेगेक्स वास्तव में सामान्य रेगेक्स की तुलना में तेज है और अपवाद की तुलना में खराब मूल्यों को संभालने में बहुत तेज है, जो कुछ समझ में आता है। परिणाम:

check_regexp with good floats: 18.001921
check_regexp with bad floats: 17.861423
check_regexp with strings: 17.558862
check_correct_regexp with good floats: 11.04428
check_correct_regexp with bad floats: 8.71211
check_correct_regexp with strings: 8.144161
check_replace with good floats: 6.020597
check_replace with bad floats: 5.343049
check_replace with strings: 5.091642
check_exception with good floats: 5.201605
check_exception with bad floats: 23.921864
check_exception with strings: 23.755481

आशा है कि यह सही है - किसी भी काउंटर उदाहरण के बारे में सुनना पसंद करेंगे। :)
डेविड लजंग मैडिसन स्टेलर

2
import re
def is_number(num):
    pattern = re.compile(r'^[-+]?[-0-9]\d*\.\d*|[-+]?\.?[0-9]\d*$')
    result = pattern.match(num)
    if result:
        return True
    else:
        return False


​>>>: is_number('1')
True

>>>: is_number('111')
True

>>>: is_number('11.1')
True

>>>: is_number('-11.1')
True

>>>: is_number('inf')
False

>>>: is_number('-inf')
False

2
क्या आप 1e6किसी संख्या का प्रतिनिधित्व करने के लिए विचार नहीं करते हैं?
मार्क डिकिंसन

1

यहाँ यह करने का मेरा सरल तरीका है। मान लीजिए कि मैं कुछ तारों के माध्यम से लूपिंग कर रहा हूं और मैं उन्हें एक सरणी में जोड़ना चाहता हूं अगर वे संख्याओं को बदल दें।

try:
    myvar.append( float(string_to_check) )
except:
    continue

Myvar.apppend को आप जो भी ऑपरेशन करना चाहते हैं उसे स्ट्रिंग से बदलें अगर यह एक नंबर हो जाए। विचार एक फ्लोट () ऑपरेशन का उपयोग करने की कोशिश करने के लिए है और यह निर्धारित करने के लिए कि क्या स्ट्रिंग एक संख्या है या नहीं, लौटे त्रुटि का उपयोग करें।


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

1

मैंने आपके द्वारा बताए गए फ़ंक्शन का भी उपयोग किया, लेकिन जल्द ही मैंने नोटिस किया कि स्ट्रिंग्स "नान", "इन्फ" के रूप में हैं और इसे विविधता के रूप में माना जाता है। इसलिए मैं आपको अपने फ़ंक्शन के उन्नत संस्करण का प्रस्ताव देता हूं, जो कि उन प्रकार के इनपुट पर गलत वापस आएगा और "1e3" वेरिएंट को विफल नहीं करेगा:

def is_float(text):
    try:
        float(text)
        # check for nan/infinity etc.
        if text.isalpha():
            return False
        return True
    except ValueError:
        return False

1

यह कोड एक्सपोजर्स, फ्लोट्स और पूर्णांक को हैंडल करता है, रेगेक्स का उपयोग करके wihtout।

return True if str1.lstrip('-').replace('.','',1).isdigit() or float(str1) else False

1

उपयोगकर्ता सहायक समारोह:

def if_ok(fn, string):
  try:
    return fn(string)
  except Exception as e:
    return None

फिर

if_ok(int, my_str) or if_ok(float, my_str) or if_ok(complex, my_str)
is_number = lambda s: any([if_ok(fn, s) for fn in (int, float, complex)])

0

आप ट्रू और फाल्स की तुलना में अधिक उपयोगी मूल्यों को वापस करके एक उपयोगी तरीके से अपवाद तकनीक को सामान्य कर सकते हैं। उदाहरण के लिए यह फ़ंक्शन उद्धरणों को गोल-गोल रखता है लेकिन संख्याओं को अकेला छोड़ देता है। आर के लिए कुछ परिवर्तनशील परिभाषा बनाने के लिए मुझे बस एक त्वरित और गंदे फिल्टर की आवश्यकता थी।

import sys

def fix_quotes(s):
    try:
        float(s)
        return s
    except ValueError:
        return '"{0}"'.format(s)

for line in sys.stdin:
    input = line.split()
    print input[0], '<- c(', ','.join(fix_quotes(c) for c in input[1:]), ')'

0

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

1 - मैं एक पूर्णांक परिणाम चाहता था यदि स्ट्रिंग एक पूर्णांक का प्रतिनिधित्व करता है

2 - मुझे डेटा संरचना में छड़ी करने के लिए एक संख्या या एक स्ट्रिंग परिणाम चाहिए था

इसलिए मैंने इस व्युत्पन्न का उत्पादन करने के लिए मूल कोड को अनुकूलित किया:

def string_or_number(s):
    try:
        z = int(s)
        return z
    except ValueError:
        try:
            z = float(s)
            return z
        except ValueError:
            return s


0
def is_float(s):
    if s is None:
        return False

    if len(s) == 0:
        return False

    digits_count = 0
    dots_count = 0
    signs_count = 0

    for c in s:
        if '0' <= c <= '9':
            digits_count += 1
        elif c == '.':
            dots_count += 1
        elif c == '-' or c == '+':
            signs_count += 1
        else:
            return False

    if digits_count == 0:
        return False

    if dots_count > 1:
        return False

    if signs_count > 1:
        return False

    return True
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.