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




casting floating-point (20)

यह जांचने का सबसे अच्छा तरीका क्या है कि स्ट्रिंग को पायथन में किसी संख्या के रूप में प्रदर्शित किया जा सकता है?

वर्तमान में मेरे पास अभी कार्य है:

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

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


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

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

एक रेगेक्स या अन्य स्ट्रिंग पार्सिंग उलझन और धीमी होगी।

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

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

  • एक संख्या, यदि संख्या मान्य है
  • एक स्टेटस कोड (उदाहरण के लिए, इरनो के माध्यम से) या अपवाद यह दिखाने के लिए कि कोई मान्य संख्या पार्स नहीं की जा सकती है।

सी (उदाहरण के रूप में) इस कई तरीकों से हैक करता है। पायथन इसे स्पष्ट रूप से और स्पष्ट रूप से बताता है।

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


जो न केवल बदसूरत और धीमी है, गुंजाइश लगता है।

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

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

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

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


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


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

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

आपका कोड मुझे ठीक लग रहा है।

शायद आपको लगता है कि अपवादों का उपयोग करने के कारण कोड "गुंजाइश" है? ध्यान दें कि पायथन प्रोग्रामर कोड कम करने योग्यता में सुधार करते समय अपवादों का उदारतापूर्वक उपयोग करते हैं, इसके कम प्रदर्शन दंड के कारण धन्यवाद।


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

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

जो केवल तभी वापस आ जाएगा जब एक या नहीं '।' अंकों की स्ट्रिंग में।

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

झूठी वापसी होगी

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


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

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

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 दोनों मामलों में जीतता है

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

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

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

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

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

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

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

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

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


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

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) 

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


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

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

स्ट्रिंग विधि - isdigit()

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


रयानन सुझाव देते हैं

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

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


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

Here's my simple way of doing it. Let's say that I'm looping through some strings and I want to add them to an array if they turn out to be numbers.

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

Replace the myvar.apppend with whatever operation you want to do with the string if it turns out to be a number. The idea is to try to use a float() operation and use the returned error to determine whether or not the string is a number.


I also used the function you mentioned, but soon I notice that strings as "Nan", "Inf" and it's variation are considered as number. So I propose you improved version of your function, that will return false on those type of input and will not fail "1e3" variants:

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

If you want to know if the entire string can be represented as a number you'll want to use a regexp (or maybe convert the float back to a string and compare it to the source string, but I'm guessing that's not very fast).


To check if the input value is a float , you can compare the type of the input to a float

def isFloat(s):
    realFloat = 0.1

    if type(s) == type(realFloat):
        return True
    else:
        return False

यह दिखाता है:

False     # s = 5
True      # s = 1.2345

मूल पोस्ट वास्तव में वापसी होगी Trueके लिए s = 5के बाद से यह एक संख्या (पूर्णांक) है और आप एक डाल सकता intएक करने के लिए floatएक के बिना ValueError। यदि आप यह सत्यापित करने का प्रयास कर रहे हैं कि यह floatकेवल एक संख्या के बजाय वास्तविक है , तो आपको उस मामले के लिए खाते की आवश्यकता होगी।


You can generalize the exception technique in a useful way by returning more useful values than True and False. For example this function puts quotes round strings but leaves numbers alone. Which is just what I needed for a quick and dirty filter to make some variable definitions for R.

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:]), ')'

You may use regex.

number = raw_input("Enter a number: ")
if re.match(r'^\d+$', number):
    print "It's integer"
    print int(number)
elif re.match(r'^\d+\.\d+$', number):
    print "It's float"
    print float(number)
else:
    print("Please enter a number")




type-conversion