जाँच करना कि पायथन में एक स्ट्रिंग को फ्लोट में परिवर्तित किया जा सकता है या नहीं


181

मुझे कुछ पायथन कोड मिला है जो स्ट्रिंग्स की सूची के माध्यम से चलता है और यदि संभव हो तो उन्हें पूर्णांक या फ्लोटिंग पॉइंट संख्या में परिवर्तित करता है। पूर्णांकों के लिए ऐसा करना बहुत आसान है

if element.isdigit():
  newelement = int(element)

फ़्लोटिंग पॉइंट नंबर अधिक कठिन हैं। अभी मैं partition('.')स्ट्रिंग को विभाजित करने और यह सुनिश्चित करने के लिए उपयोग कर रहा हूं कि यह सुनिश्चित करने के लिए कि एक या दोनों पक्ष अंक हैं।

partition = element.partition('.')
if (partition[0].isdigit() and partition[1] == '.' and partition[2].isdigit()) 
    or (partition[0] == '' and partition[1] == '.' and partition[2].isdigit()) 
    or (partition[0].isdigit() and partition[1] == '.' and partition[2] == ''):
  newelement = float(element)

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

किसी के पास कोई अन्य विचार है? विभाजन के सापेक्ष गुणों पर राय और दृष्टिकोण को पकड़ने / आज़माने के लिए?

जवाबों:


304

मैं सिर्फ इस्तेमाल करेंगे ..

try:
    float(element)
except ValueError:
    print "Not a float"

..यह सरल है, और यह काम करता है

एक अन्य विकल्प एक नियमित अभिव्यक्ति होगी:

import re
if re.match(r'^-?\d+(?:\.\d+)?$', element) is None:
    print "Not float"

3
@ एस.लॉट: इस पर लागू होने वाले अधिकांश तार, चींटियों या तैरने वाले होते हैं।
क्रिस अपचर्च

10
आपका रेगेक्स इष्टतम नहीं है। "^ \ d + \। \ d + $" ऊपर के समान गति से एक मैच में विफल हो जाएगा, लेकिन तेजी से सफल होगा। इसके अलावा, एक और सही तरीका होगा: "^ [+]? \ D? (>? \ _ \ _ D + $!"), हालांकि, वह अभी भी संख्याओं से मेल नहीं खाता है जैसे: + 1.0e-10
जॉन गीत्ज़ेन

86
सिवाय इसके कि आप अपने फ़ंक्शन "will_it_float" का नाम देना भूल गए।
अपराह्न

3
दूसरा विकल्प नैनो और घातीय अभिव्यक्ति को नहीं पकड़ेगा - जैसे कि 2e3।
पैट्रिक बी।

4
मुझे लगता है कि रेगेक्स नकारात्मक संख्या को पार्स नहीं कर रहा है।
कार्लोस

191

फ्लोट की जांच के लिए पायथन विधि:

def isfloat(value):
  try:
    float(value)
    return True
  except ValueError:
    return False

फ्लोट बोट में छिपकर रहने वाले गोबलिनों से थोड़ा मत बनो! परीक्षण का उपयोग करें!

क्या है, और एक फ्लोट नहीं है जो आपको आश्चर्यचकित कर सकता है:

Command to parse                        Is it a float?  Comment
--------------------------------------  --------------- ------------
print(isfloat(""))                      False
print(isfloat("1234567"))               True 
print(isfloat("NaN"))                   True            nan is also float
print(isfloat("NaNananana BATMAN"))     False
print(isfloat("123.456"))               True
print(isfloat("123.E4"))                True
print(isfloat(".1"))                    True
print(isfloat("1,234"))                 False
print(isfloat("NULL"))                  False           case insensitive
print(isfloat(",1"))                    False           
print(isfloat("123.EE4"))               False           
print(isfloat("6.523537535629999e-07")) True
print(isfloat("6e777777"))              True            This is same as Inf
print(isfloat("-iNF"))                  True
print(isfloat("1.797693e+308"))         True
print(isfloat("infinity"))              True
print(isfloat("infinity and BEYOND"))   False
print(isfloat("12.34.56"))              False           Two dots not allowed.
print(isfloat("#56"))                   False
print(isfloat("56%"))                   False
print(isfloat("0E0"))                   True
print(isfloat("x86E0"))                 False
print(isfloat("86-5"))                  False
print(isfloat("True"))                  False           Boolean is not a float.   
print(isfloat(True))                    True            Boolean is a float
print(isfloat("+1e1^5"))                False
print(isfloat("+1e1"))                  True
print(isfloat("+1e1.3"))                False
print(isfloat("+1.3P1"))                False
print(isfloat("-+1"))                   False
print(isfloat("(1)"))                   False           brackets not interpreted

6
बहुत बढ़िया जवाब। बस 2 और जोड़ रहा है जहां फ्लोट = ट्रू: isfloat(" 1.23 ")और isfloat(" \n \t 1.23 \n\t\n")। वेब अनुरोधों में उपयोगी; पहले सफेद रिक्त स्थान को ट्रिम करने की कोई आवश्यकता नहीं है।
३oder बजे बरनीकेडरकोडर

22
'1.43'.replace('.','',1).isdigit()

जो trueएक या एक नहीं है, तो ही वापस आएगा । ' अंकों की कड़ी में।

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

वापस होगा false

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

वापस होगा false


3
इष्टतम नहीं है, लेकिन वास्तव में बहुत चालाक है। +/- और एक्सप्लॉर्स को हैंडल नहीं करेंगे।
मैड फिजिसिस्ट

साल देर से, लेकिन यह एक अच्छा तरीका है। एक पांडा डेटाफ़्रेम में निम्नलिखित का उपयोग करके मेरे लिए काम किया:[i for i in df[i].apply(lambda x: str(x).replace('.','').isdigit()).any()]
मार्क मोरेटो

1
@MarkMoretto जब आप नकारात्मक संख्याओं के अस्तित्व के बारे में जानेंगे, तो आप एक झटके में होने वाले हैं
डेविड हेफर्नन

मेरे परिदृश्य के लिए सर्वश्रेष्ठ एक-लाइनर, जहां मुझे केवल सकारात्मक फ़्लोट्स या संख्याओं की जांच करने की आवश्यकता है। मुझे पसंद है।
MJohnyJ

8

टीएल; डीआर :

  • यदि आपका इनपुट ज्यादातर तार है जिसे फ्लोट में परिवर्तित किया जा सकता है, तो try: except:विधि सबसे अच्छा देशी पायथन विधि है।
  • यदि आपका इनपुट अधिकतर स्ट्रिंग्स है, जिसे फ्लोट्स में परिवर्तित नहीं किया जा सकता है, तो नियमित एक्सप्रेशन या पार्टीशन विधि बेहतर होगी।
  • यदि आप अपने इनपुट के 1) अनिश्चित हैं या अधिक गति और 2 की आवश्यकता है) तो कोई आपत्ति नहीं है और एक तृतीय-पक्ष सी-एक्सटेंशन स्थापित कर सकता है, फास्टनर बहुत अच्छी तरह से काम करता है।

थर्ड-पार्टी मॉड्यूल के माध्यम से उपलब्ध एक और तरीका है जिसे फास्टनर्स (प्रकटीकरण, मैं लेखक हूं) कहा जाता है ; यह एक फ़ंक्शन प्रदान करता है जिसे इफ़्लोत कहा जाता है । मैंने इस जवाब में जैकब गेब्रियलसन द्वारा उल्लिखित सबसे सटीक उदाहरण लिया है , लेकिन इस fastnumbers.isfloatविधि को जोड़ा है । मुझे यह भी ध्यान देना चाहिए कि जैकब के उदाहरण ने रेगेक्स विकल्प के साथ न्याय नहीं किया, क्योंकि उस उदाहरण में अधिकांश समय डॉट ऑपरेटर के कारण वैश्विक लुकअप में बिताया गया था ... मैंने उस फ़ंक्शन को एक तुलनात्मक रूप से तुलना करने के लिए संशोधित किया है try: except:


def is_float_try(str):
    try:
        float(str)
        return True
    except ValueError:
        return False

import re
_float_regexp = re.compile(r"^[-+]?(?:\b[0-9]+(?:\.[0-9]*)?|\.[0-9]+\b)(?:[eE][-+]?[0-9]+\b)?$").match
def is_float_re(str):
    return True if _float_regexp(str) else False

def is_float_partition(element):
    partition=element.partition('.')
    if (partition[0].isdigit() and partition[1]=='.' and partition[2].isdigit()) or (partition[0]=='' and partition[1]=='.' and partition[2].isdigit()) or (partition[0].isdigit() and partition[1]=='.' and partition[2]==''):
        return True
    else:
        return False

from fastnumbers import isfloat


if __name__ == '__main__':
    import unittest
    import timeit

    class ConvertTests(unittest.TestCase):

        def test_re_perf(self):
            print
            print 're sad:', timeit.Timer('ttest.is_float_re("12.2x")', "import ttest").timeit()
            print 're happy:', timeit.Timer('ttest.is_float_re("12.2")', "import ttest").timeit()

        def test_try_perf(self):
            print
            print 'try sad:', timeit.Timer('ttest.is_float_try("12.2x")', "import ttest").timeit()
            print 'try happy:', timeit.Timer('ttest.is_float_try("12.2")', "import ttest").timeit()

        def test_fn_perf(self):
            print
            print 'fn sad:', timeit.Timer('ttest.isfloat("12.2x")', "import ttest").timeit()
            print 'fn happy:', timeit.Timer('ttest.isfloat("12.2")', "import ttest").timeit()


        def test_part_perf(self):
            print
            print 'part sad:', timeit.Timer('ttest.is_float_partition("12.2x")', "import ttest").timeit()
            print 'part happy:', timeit.Timer('ttest.is_float_partition("12.2")', "import ttest").timeit()

    unittest.main()

मेरी मशीन पर, आउटपुट है:

fn sad: 0.220988988876
fn happy: 0.212214946747
.
part sad: 1.2219619751
part happy: 0.754667043686
.
re sad: 1.50515985489
re happy: 1.01107215881
.
try sad: 2.40243887901
try happy: 0.425730228424
.
----------------------------------------------------------------------
Ran 4 tests in 7.761s

OK

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


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

5

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

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

$ ./floatstr.py
एफ ..
विभाजन दुखद: 3.1102449894
विभाजन खुश: 2.09208488464
..
फिर से उदास: 7.76906108856
फिर से खुश: 7.09421992302
..
दु: खी प्रयास करें: 12.1525540352
खुश कोशिश करें: 1.44165301323
।
================================================== ====================
विफल: test_partition (__main __। ConvertTests)
-------------------------------------------------- --------------------
ट्रेसबैक (सबसे हालिया कॉल अंतिम):
  फ़ाइल "./floatstr.py", लाइन 48, test_partition में
    self.failUnless (is_float_partition ( "20e2"))
AssertionError

-------------------------------------------------- --------------------
33.670 में रन 8 टेस्ट

विफल (विफल = 1)

यहाँ कोड (पायथन 2.6, जॉन गिएत्जन के जवाब से लिया गया रेक्सएक्सप ) है:

def is_float_try(str):
    try:
        float(str)
        return True
    except ValueError:
        return False

import re
_float_regexp = re.compile(r"^[-+]?(?:\b[0-9]+(?:\.[0-9]*)?|\.[0-9]+\b)(?:[eE][-+]?[0-9]+\b)?$")
def is_float_re(str):
    return re.match(_float_regexp, str)


def is_float_partition(element):
    partition=element.partition('.')
    if (partition[0].isdigit() and partition[1]=='.' and partition[2].isdigit()) or (partition[0]=='' and partition[1]=='.' and pa\
rtition[2].isdigit()) or (partition[0].isdigit() and partition[1]=='.' and partition[2]==''):
        return True

if __name__ == '__main__':
    import unittest
    import timeit

    class ConvertTests(unittest.TestCase):
        def test_re(self):
            self.failUnless(is_float_re("20e2"))

        def test_try(self):
            self.failUnless(is_float_try("20e2"))

        def test_re_perf(self):
            print
            print 're sad:', timeit.Timer('floatstr.is_float_re("12.2x")', "import floatstr").timeit()
            print 're happy:', timeit.Timer('floatstr.is_float_re("12.2")', "import floatstr").timeit()

        def test_try_perf(self):
            print
            print 'try sad:', timeit.Timer('floatstr.is_float_try("12.2x")', "import floatstr").timeit()
            print 'try happy:', timeit.Timer('floatstr.is_float_try("12.2")', "import floatstr").timeit()

        def test_partition_perf(self):
            print
            print 'partition sad:', timeit.Timer('floatstr.is_float_partition("12.2x")', "import floatstr").timeit()
            print 'partition happy:', timeit.Timer('floatstr.is_float_partition("12.2")', "import floatstr").timeit()

        def test_partition(self):
            self.failUnless(is_float_partition("20e2"))

        def test_partition2(self):
            self.failUnless(is_float_partition(".2"))

        def test_partition3(self):
            self.failIf(is_float_partition("1234x.2"))

    unittest.main()

4

बस विविधता के लिए यहां एक और तरीका है।

>>> all([i.isnumeric() for i in '1.2'.split('.',1)])
True
>>> all([i.isnumeric() for i in '2'.split('.',1)])
True
>>> all([i.isnumeric() for i in '2.f'.split('.',1)])
False

संपादित करें: यकीन है कि यह फ्लोट के सभी मामलों तक नहीं होगा, खासकर जब एक घातांक होता है। हल करने के लिए यह इस तरह दिखता है। यह लौटेगा सच केवल वैल एक नाव है और उदाहरण के लिए गलत है, लेकिन शायद रेगेक्स की तुलना में कम प्रदर्शन है।

>>> def isfloat(val):
...     return all([ [any([i.isnumeric(), i in ['.','e']]) for i in val],  len(val.split('.')) == 2] )
...
>>> isfloat('1')
False
>>> isfloat('1.2')
True
>>> isfloat('1.2e3')
True
>>> isfloat('12e3')
False

विभिन्न प्रकार के यूनिकोड वर्णों पर सही होने पर, सम्‍मिलित फ़ंक्शन एक खराब पसंद की तरह दिखता है। डॉक्स कहते हैं: "न्यूमेरिक वर्णों में अंक वर्ण शामिल हैं, और उन सभी वर्णों में यूनिकोड संख्यात्मक मान गुण हैं, जैसे U + 2155, वल्गर फ्रैक्शन वन
फिफ्टी

3

यह रेगेक्स वैज्ञानिक फ्लोटिंग पॉइंट नंबरों की जाँच करेगा:

^[-+]?(?:\b[0-9]+(?:\.[0-9]*)?|\.[0-9]+\b)(?:[eE][-+]?[0-9]+\b)?$

हालांकि, मेरा मानना ​​है कि एक कोशिश में पार्सर का उपयोग करने के लिए आपका सबसे अच्छा शर्त है।


2

यदि आपको संख्याओं के वैज्ञानिक या अन्य भावों के बारे में चिंता करने की आवश्यकता नहीं है और वे केवल उन तारों के साथ काम कर रहे हैं जो किसी अवधि के साथ या बिना संख्या के हो सकते हैं:

समारोह

def is_float(s):
    result = False
    if s.count(".") == 1:
        if s.replace(".", "").isdigit():
            result = True
    return result

लैम्ब्डा संस्करण

is_float = lambda x: x.replace('.','',1).isdigit() and "." in x

उदाहरण

if is_float(some_string):
    some_string = float(some_string)
elif some_string.isdigit():
    some_string = int(some_string)
else:
    print "Does not convert to int or float."

इस तरह आप अकस्मात रूप से परिवर्तित नहीं हो सकते हैं जो एक इंट, एक फ्लोट में होना चाहिए।


2

फ़ंक्शन का सरलीकृत संस्करण is_digit(str) , जो अधिकांश मामलों में होता है ( घातीय संकेतन और "NaN" मान पर विचार नहीं करता है ):

def is_digit(str):
    return str.lstrip('-').replace('.', '').isdigit()

1

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

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

1
क्या हम if text.isalpha():अभी से जाँच शुरू नहीं कर सकते?
सेसाबा तोथ

BTW मुझे वही चाहिए: मैं NaN, Inf और सामान स्वीकार नहीं करना चाहता
Csaba Toth

1

फ्लोट में बदलने का प्रयास करें। यदि कोई त्रुटि है, तो ValueError अपवाद मुद्रित करें।

try:
    x = float('1.23')
    print('val=',x)
    y = float('abc')
    print('val=',y)
except ValueError as err:
    print('floatErr;',err)

आउटपुट:

val= 1.23
floatErr: could not convert string to float: 'abc'

1

डिक्शनरी को तर्क के रूप में पारित करने से यह तार बदल जाएगा जिसे फ्लोट में परिवर्तित किया जा सकता है और दूसरों को छोड़ देगा

def covertDict_float(data):
        for i in data:
            if data[i].split(".")[0].isdigit():
                try:
                    data[i] = float(data[i])
                except:
                    continue
        return data

0

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

def cleanInput(question,retry=False): 
    inputValue = input("\n\nOnly positive numbers can be entered, please re-enter the value.\n\n{}".format(question)) if retry else input(question)
    try:
        if float(inputValue) <= 0 : raise ValueError()
        else : return(float(inputValue))
    except ValueError : return(cleanInput(question,retry=True))


willbefloat = cleanInput("Give me the number: ")

0
def try_parse_float(item):
  result = None
  try:
    float(item)
  except:
    pass
  else:
    result = float(item)
  return result

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

0

मैंने ऊपर दिए गए कुछ सरल विकल्पों की कोशिश की, एक फ्लोट में परिवर्तित करने के लिए एक परीक्षण परीक्षण का उपयोग करके, और पाया कि अधिकांश उत्तरों में एक समस्या है।

सरल परीक्षण (उपरोक्त उत्तरों की तर्ज पर):

entry = ttk.Entry(self, validate='key')
entry['validatecommand'] = (entry.register(_test_num), '%P')

def _test_num(P):
    try: 
        float(P)
        return True
    except ValueError:
        return False

समस्या तब आती है जब:

  • आप एक नकारात्मक संख्या शुरू करने के लिए '-' दर्ज करते हैं:

आप तब प्रयास कर रहे हैं float('-')जो विफल हो जाता है

  • आप एक नंबर दर्ज करते हैं, लेकिन फिर सभी अंकों को हटाने का प्रयास करते हैं

आप फिर कोशिश कर रहे हैं float('')जो इसी तरह विफल भी है

मेरे पास त्वरित समाधान है:

def _test_num(P):
    if P == '' or P == '-': return True
    try: 
        float(P)
        return True
    except ValueError:
        return False

-2
str(strval).isdigit()

सरल प्रतीत होता है।

मान को एक स्ट्रिंग या इंट या फ्लोट के रूप में संग्रहीत किया जाता है


में [2]: '123,123'.isdigit () बाहर [2]: गलत
Daniil Mashkin

1
यह नकारात्मक संख्याओं के लिए काम नहीं करता है, कृपया अपने उत्तर को ठीक करें
रैंडम ईली

'39 .1'.isdigit ()
द लाड

all ([x.isdigit () in x for str (VAR) .strip ('-')। प्रतिस्थापित करें (',', '' '') विभाजित करें ('।')]) यदि आप अधिक पूर्ण खोज रहे हैं। कार्यान्वयन।
लॉटरी 25
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.