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

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

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

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

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

Ответы [ 33 ]

4 голосов
/ 12 октября 2010

Я сделал тест скорости. Допустим, что если строка является вероятным числом, стратегия попытка / исключение является самой быстрой из возможных. и вы заинтересованы в проверке Integer , стоит провести некоторый тест (isdigit плюс заголовок '-'). Если вы хотите проверить число с плавающей запятой, вы должны использовать try / кроме кода без выхода.

3 голосов
/ 29 июля 2013

РайанН предлагает

Если вы хотите вернуть False для NaN и Inf, измените строку на x = float (s); return (x == x) и (x - 1! = x). Это должно вернуть True для всех чисел, кроме Inf и NaN

Но это не совсем работает, потому что для достаточно больших значений с плавающей запятой x-1 == x возвращает true. Например, 2.0**54 - 1 == 2.0**54

1 голос
/ 16 декабря 2018

Этот код обрабатывает показатели, числа с плавающей точкой и целые числа без использования регулярных выражений.

return True if str1.lstrip('-').replace('.','',1).isdigit() or float(str1) else False
1 голос
/ 11 мая 2019

Я думаю, что ваше решение в порядке.

Сказав это, в этих ответах много ненависти к регулярным выражениям, которые, на мой взгляд, неоправданны, регулярные выражения могут быть достаточно чистыми, правильными и быстрыми. Это действительно зависит от того, что вы пытаетесь сделать. Первоначальный вопрос заключался в том, как можно «проверить, можно ли представить строку в виде числа (с плавающей запятой)» (согласно вашему названию). Предположительно, вы захотите использовать числовое значение / значение с плавающей запятой после того, как вы проверите, что оно допустимо, и в этом случае ваша попытка / исключение имеет большой смысл. Но если по какой-то причине вы просто хотите проверить, что строка является числом , тогда регулярное выражение также работает нормально, но его трудно получить правильно. Я думаю, что большинство ответов на регулярные выражения до сих пор, например, неправильно анализируют строки без целочисленной части (такой как ".7"), которая является плавающей точкой в ​​том, что касается python. И это немного сложно проверить в одном регулярном выражении, где дробная часть не требуется. Я включил два регулярных выражения, чтобы показать это.

Это поднимает интересный вопрос о том, что такое «число». Вы включаете "inf", который является допустимым как float в python? Или вы включаете числа, которые являются «числами», но, возможно, не могут быть представлены в Python (например, числа, которые больше, чем максимум с плавающей точкой).

Есть также неясности в том, как вы анализируете числа. Например, как насчет "--20"? Это «число»? Это законный способ представлять «20»? Python позволит вам сделать "var = --20" и установить его в 20 (хотя на самом деле это потому, что он обрабатывает это как выражение), но float ("- 20") не работает.

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

# 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
1 голос
/ 16 октября 2016

Я также использовал функцию, которую вы упомянули, но вскоре я заметил, что строки как «Nan», «Inf» и их вариация считаются числом. Поэтому я предлагаю вам улучшенную версию вашей функции, которая будет возвращать false при вводе такого типа и не потерпит неудачу при вариантах «1e3»:

def is_float(text):
    try:
        float(text)
        # check for nan/infinity etc.
        if text.isalpha():
            return False
        return True
    except ValueError:
        return False
0 голосов
/ 10 декабря 2008

Если вы хотите знать, может ли строка whole быть представлена ​​как число, вы захотите использовать регулярное выражение (или, возможно, преобразовать число с плавающей точкой обратно в строку и сравнить ее с исходной строкой, но я предполагаю, что это не очень быстро).

0 голосов
/ 02 августа 2018
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 голосов
/ 18 марта 2018

У меня похожая проблема. Вместо определения функции isNumber я хочу преобразовать список строк в число с плавающей точкой, что в терминах высокого уровня будет:

[ float(s) for s in list if isFloat(s)]

Это данность, мы не можем отделить float (s) от функций isFloat (s): эти два результата должны возвращаться одной и той же функцией. Кроме того, если float (s) терпит неудачу, весь процесс завершается неудачей, вместо того, чтобы просто игнорировать неисправный элемент. Кроме того, «0» является действительным числом и должно быть включено в список. При фильтрации плохих элементов не исключайте 0.

Следовательно, вышеприведенное понимание должно быть как-то изменено на:

  • если какой-либо элемент в списке не может быть преобразован, игнорируйте его и не создавайте исключение
  • избегать вызова float (s) более одного раза для каждого элемента (один для преобразования, другой для теста)
  • если преобразованное значение равно 0, оно все равно должно присутствовать в окончательном списке

Я предлагаю решение, основанное на Nullable числовых типах C #. Эти типы внутренне представлены структурой, которая имеет числовое значение и добавляет логическое значение, указывающее, является ли значение допустимым:

def tryParseFloat(s):
    try:
        return(float(s), True)
    except:
        return(None, False)

tupleList = [tryParseFloat(x) for x in list]
floats = [v for v,b in tupleList if b]
0 голосов
/ 16 июля 2009

Вот мой простой способ сделать это. Допустим, я перебираю некоторые строки и хочу добавить их в массив, если они окажутся числами.

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

Замените myvar.apppend любой операцией, которую вы хотите выполнить со строкой, если она окажется числом. Идея состоит в том, чтобы попытаться использовать операцию float () и использовать возвращаемую ошибку, чтобы определить, является ли строка числом.

0 голосов
/ 24 февраля 2017

используйте следующие действия для всех случаев: -

import re
a=re.match('((\d+[\.]\d*$)|(\.)\d+$)' ,  '2.3') 
a=re.match('((\d+[\.]\d*$)|(\.)\d+$)' ,  '2.')
a=re.match('((\d+[\.]\d*$)|(\.)\d+$)' ,  '.3')
a=re.match('((\d+[\.]\d*$)|(\.)\d+$)' ,  '2.3sd')
a=re.match('((\d+[\.]\d*$)|(\.)\d+$)' ,  '2.3')
...