Как проверить, является ли строка числом (с плавающей запятой)? - PullRequest
1418 голосов
/ 09 декабря 2008

Каков наилучший способ проверить, может ли строка представляться как число в Python?

У меня сейчас есть функция:

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

Что не только уродливо и медленно, но кажется неуклюжим. Однако я не нашел лучшего метода, потому что вызов float в основной функции еще хуже.

Ответы [ 33 ]

12 голосов
/ 05 января 2016

Я знаю, что это особенно старо, но я бы добавил ответ, который, как мне кажется, охватывает информацию, отсутствующую в ответе с наибольшим количеством голосов, который может быть очень ценным для любого, кто найдет это:

Для каждого из следующих методов соедините их со счетчиком, если вам нужно, чтобы какой-либо ввод был принят. (Предполагается, что мы используем голосовые определения целых чисел, а не 0-255 и т. Д.)

x.isdigit() хорошо работает для проверки, является ли х целым числом.

x.replace('-','').isdigit() хорошо работает для проверки, если х является отрицательным. (Проверка - в первой позиции)

x.replace('.','').isdigit() хорошо работает для проверки, является ли x десятичным.

x.replace(':','').isdigit() хорошо работает для проверки, если х является отношением.

x.replace('/','',1).isdigit() хорошо работает для проверки, если х является дробью.

11 голосов
/ 09 декабря 2008

Приведение к float и перехват ValueError, вероятно, самый быстрый способ, так как float () специально предназначен именно для этого. Все остальное, требующее разбора строк (регулярное выражение и т. Д.), Вероятно, будет медленнее из-за того, что оно не настроено для этой операции. Мои $ 0,02.

11 голосов
/ 04 марта 2013

Вы можете использовать строки Unicode, у них есть метод, который делает то, что вы хотите:

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

9 голосов
/ 16 января 2013

Я хотел посмотреть, какой метод самый быстрый. В целом лучшие и наиболее последовательные результаты были получены с помощью функции check_replace. Самые быстрые результаты были получены с помощью функции check_exception, но только в том случае, если не было сгенерировано исключение - это означает, что его код является наиболее эффективным, но издержки на создание исключения довольно велики.

Обратите внимание, что проверка на успешное приведение является единственным точным методом, например, он работает с check_exception, но две другие тестовые функции вернут False для действительного числа с плавающей запятой:

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

Вот результаты с Python 2.7.10 на MacBook Pro 13:

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

Вот результаты с Python 3.6.5 на MacBook Pro 13:

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

Вот результаты PyPy 2.7.13 на MacBook Pro 13 в 2017 году:

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
9 голосов
/ 11 февраля 2018

Этот ответ содержит пошаговое руководство, содержащее функцию с примерами для поиска строки:

  • Положительное целое число
  • Положительный / отрицательный - целое число / число с плавающей запятой
  • Как отбросить строки "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" (не число), потому что для Python это допустимое число с плавающей точкой, представляющее, что это не число. Например:

>>> is_number('NaN')
True

Чтобы проверить, является ли число «NaN», вы можете использовать math.isnan() как:

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

>>> math.isnan(nan_num)
True

Или, если вы не хотите импортировать дополнительную библиотеку, чтобы проверить это, вы можете просто проверить ее, сравнив ее с самой собой, используя ==. Python возвращает False, когда nan float сравнивается с самим собой. Например:

# `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

PS: Каждая операция для каждой проверки в зависимости от типа номера сопровождается дополнительными издержками. Выберите версию функции is_number, которая соответствует вашим требованиям.

7 голосов
/ 13 октября 2014

Допустим, у вас есть цифры в строке. str = "100949" и вы хотели бы проверить, есть ли у него только цифры

if str.isdigit():
returns TRUE or FALSE 

isdigit docs

в противном случае ваш метод отлично работает, чтобы найти в строке цифру.

6 голосов
/ 23 марта 2012

Таким образом, чтобы сложить все вместе, проверяя Nan, бесконечность и комплексные числа (казалось бы, они указаны с помощью j, а не i, т.е. 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
5 голосов
/ 11 декабря 2008

Твой код мне подходит.

Возможно, вы думаете, что код "неуклюжий" из-за использования исключений? Обратите внимание, что программисты на Python склонны свободно использовать исключения, когда это улучшает читабельность кода благодаря низкому снижению производительности.

4 голосов
/ 03 июля 2014

Мне нужно было определить, приведена ли строка к базовым типам (float, 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) 
4 голосов
/ 06 октября 2018

Ввод может быть следующим:

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

что такое ast ?


2- Если вы уверены, что переменное содержимое равно String :

использовать 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
...