How do I check if a string is a number (float)?

后端 未结 30 3916
暗喜
暗喜 2020-11-21 05:16

What is the best possible way to check if a string can be represented as a number in Python?

The function I currently have right now is:

def is_numb         


        
相关标签:
30条回答
  • 2020-11-21 05:37

    Which, not only is ugly and slow, seems clunky.

    It may take some getting used to, but this is the pythonic way of doing it. As has been already pointed out, the alternatives are worse. But there is one other advantage of doing things this way: polymorphism.

    The central idea behind duck typing is that "if it walks and talks like a duck, then it's a duck." What if you decide that you need to subclass string so that you can change how you determine if something can be converted into a float? Or what if you decide to test some other object entirely? You can do these things without having to change the above code.

    Other languages solve these problems by using interfaces. I'll save the analysis of which solution is better for another thread. The point, though, is that python is decidedly on the duck typing side of the equation, and you're probably going to have to get used to syntax like this if you plan on doing much programming in Python (but that doesn't mean you have to like it of course).

    One other thing you might want to take into consideration: Python is pretty fast in throwing and catching exceptions compared to a lot of other languages (30x faster than .Net for instance). Heck, the language itself even throws exceptions to communicate non-exceptional, normal program conditions (every time you use a for loop). Thus, I wouldn't worry too much about the performance aspects of this code until you notice a significant problem.

    0 讨论(0)
  • 2020-11-21 05:37

    You can use Unicode strings, they have a method to do just what you want:

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

    Or:

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

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

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

    0 讨论(0)
  • 2020-11-21 05:39
    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
    
    0 讨论(0)
  • 2020-11-21 05:41

    There is one exception that you may want to take into account: the string 'NaN'

    If you want is_number to return FALSE for 'NaN' this code will not work as Python converts it to its representation of a number that is not a number (talk about identity issues):

    >>> float('NaN')
    nan
    

    Otherwise, I should actually thank you for the piece of code I now use extensively. :)

    G.

    0 讨论(0)
  • 2020-11-21 05:41

    I know this is particularly old but I would add an answer I believe covers the information missing from the highest voted answer that could be very valuable to any who find this:

    For each of the following methods connect them with a count if you need any input to be accepted. (Assuming we are using vocal definitions of integers rather than 0-255, etc.)

    x.isdigit() works well for checking if x is an integer.

    x.replace('-','').isdigit() works well for checking if x is a negative.(Check - in first position)

    x.replace('.','').isdigit() works well for checking if x is a decimal.

    x.replace(':','').isdigit() works well for checking if x is a ratio.

    x.replace('/','',1).isdigit() works well for checking if x is a fraction.

    0 讨论(0)
  • 2020-11-21 05:43

    TL;DR The best solution is s.replace('.','',1).isdigit()

    I did some benchmarks comparing the different approaches

    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()
    

    If the string is not a number, the except-block is quite slow. But more importantly, the try-except method is the only approach that handles scientific notations correctly.

    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__)
    

    Float notation ".1234" is not supported by:
    - 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__)
    

    Scientific notation "1.000000e+50" is not supported by:
    - is_number_regex
    - is_number_repl_isdigit
    Scientific notation "1e50" is not supported by:
    - is_number_regex
    - is_number_repl_isdigit

    EDIT: The benchmark results

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

    where the following functions were tested

    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()
    

    0 讨论(0)
提交回复
热议问题