Как мне проверить, является ли строка числом (с плавающей точкой)?

StackOverflow https://stackoverflow.com/questions/354038

Вопрос

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

Функция, которая у меня сейчас есть, это:

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

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

Это было полезно?

Решение

Что не только уродливо и медленно

Я бы оспорил и то, и другое.

Регулярное выражение или другой метод синтаксического анализа строк был бы уродливее и медленнее.

Я не уверен, что что-то намного может быть быстрее, чем описано выше.Он вызывает функцию и возвращает результат.Попытка / Catch не приводит к большим накладным расходам, потому что наиболее распространенное исключение перехватывается без тщательного поиска кадров стека.

Проблема в том, что любая функция числового преобразования имеет два вида результатов

  • Номер, если этот номер действителен
  • Код состояния (например, через errno) или исключение, чтобы показать, что не удалось разобрать ни один допустимый номер.

C (в качестве примера) обходит это несколькими способами.Python излагает это четко и недвусмысленно.

Я думаю, что ваш код для этого идеален.

Другие советы

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

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

Строковые методы - isdigit(): Python2, Python3

Есть также кое-что в строках Unicode, с которыми я не слишком знаком Юникод - Это десятичный код/decimal

TL;DR Лучшим решением является s.replace('.','',1).isdigit()

Я сделал кое - что контрольные показатели сравнение различных подходов

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

Если строка не является числом, блок исключений выполняется довольно медленно.Но что еще более важно, метод try-except - это единственный подход, который правильно обрабатывает научные обозначения.

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

Плавающая нотация ".1234" не поддерживается:
- is_number_regex - это_число_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__)

Научное обозначение "1.000000e +50" не поддерживается:
- is_number_regex - это_число_regex
- is_number_repl_isdigit - это цифра
Научное обозначение "1e50" не поддерживается:
- is_number_regex - это_число_regex
- is_number_repl_isdigit - это цифра

Редактировать:Результаты бенчмарка

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

где были протестированы следующие функции

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

enter image description here

Есть одно исключение, которое вы, возможно, захотите принять во внимание:строка "NaN"

Если вы хотите, чтобы is_number возвращал FALSE для 'NaN', этот код не будет работать, поскольку Python преобразует его в свое представление числа, которое не является числом (поговорим о проблемах с идентификацией):

>>> float('NaN')
nan

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

G.

как насчет этого:

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

который вернет значение true только в том случае, если в строке цифр есть одно или вообще нет '.'.

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

вернет значение false

Редактировать:только что увидел еще один комментарий ...добавление .replace(badstuff,'',maxnum_badstuff) для других случаев это можно сделать.если вы добавляете соль, а не произвольные приправы (см.:xkcd#974) это прекрасно подойдет: P

Обновлено после того, как Альфе указал, что вам не нужно проверять наличие float отдельно, поскольку complex обрабатывает оба параметра:

def is_number(s):
    try:
        complex(s) # for int, long, float and complex
    except ValueError:
        return False

    return True

Ранее сказанное:В некоторых редких случаях вам также может потребоваться проверить наличие комплексных чисел (например1 + 2i), который не может быть представлен символом float:

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

Который не только уродлив и медлителен, но и кажется неуклюжим.

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

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

Другие языки решают эти проблемы с помощью интерфейсов.Я сохраню анализ того, какое решение лучше, для другого потока.Дело, однако, в том, что python явно находится на стороне утиного ввода в уравнении, и вам, вероятно, придется привыкнуть к подобному синтаксису, если вы планируете много программировать на Python (но это, конечно, не значит, что вам это должно нравиться).

Еще одна вещь, которую вы, возможно, захотите принять во внимание:Python довольно быстр в создании и перехвате исключений по сравнению со многими другими языками (в 30 раз быстрее, чем .Например, Net).Черт возьми, сам язык даже генерирует исключения для передачи неисключительных, нормальных условий программы (каждый раз, когда вы используете цикл for).Таким образом, я бы не стал слишком беспокоиться об аспектах производительности этого кода, пока вы не заметите существенную проблему.

Для 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

Просто Имитируйте C#

В C # есть две разные функции, которые обрабатывают синтаксический анализ скалярных значений:

  • Плавающий.Синтаксический анализ ()
  • Плавающий.Попробуйте проанализировать ()

float.parse():

def parse(string):
    try:
        return float(string)
    except Exception:
        throw TypeError

Примечание:Если вам интересно, почему я изменил исключение на TypeError, вот документация.

float.try_parse():

def try_parse(string, fail=None):
    try:
        return float(string)
    except Exception:
        return fail;

Примечание:Вы не хотите возвращать логическое значение 'False', потому что это все еще тип значения.Нет ничего лучше, потому что это указывает на неудачу.Конечно, если вы хотите что-то другое, вы можете изменить параметр fail на любой, какой захотите.

Чтобы расширить float, включив в него 'parse()' и 'try_parse()', вам нужно будет изменить класс 'float', чтобы добавить эти методы.

Если вы хотите уважать уже существующие функции, код должен быть чем-то вроде:

def monkey_patch():
    if(!hasattr(float, 'parse')):
        float.parse = parse
    if(!hasattr(float, 'try_parse')):
        float.try_parse = try_parse

Побочное примечание:Лично я предпочитаю называть это Обезьяньим ударом, потому что мне кажется, что я злоупотребляю языком, когда делаю это, но YMMV.

Использование:

float.parse('giggity') // throws TypeException
float.parse('54.3') // returns the scalar value 54.3
float.tryParse('twank') // returns None
float.tryParse('32.2') // returns the scalar value 32.2

И великий Мудрец Питонас сказал Святому Престолу Шарписусу: "Все, что ты можешь сделать, я могу сделать лучше;Я могу сделать все лучше тебя.

Для строк, не содержащих чисел, try: except: на самом деле это медленнее, чем регулярные выражения.Для строк с допустимыми числами регулярное выражение выполняется медленнее.Итак, подходящий метод зависит от ваших входных данных.

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


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: был быстрым для числового ввода, но очень медленным для неверного ввода
  • регулярное выражение очень эффективно, когда входные данные недопустимы
  • fastnumbers выигрывает в обоих случаях

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

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

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

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

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

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

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

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

Вы можете использовать строки 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

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

  • Положительное целое число
  • Положительное / отрицательное - целое число / с плавающей точкой
  • Как отбросить строки "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 функция, которая соответствует вашим требованиям.

Я хотел посмотреть, какой метод самый быстрый.В целом наилучшие и наиболее последовательные результаты были получены 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 2017 года выпуска:

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 2017 года выпуска:

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

Итак, чтобы собрать все это вместе, проверяя наличие 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

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

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

Входные данные могут быть следующими:

a="50" b=50 c=50.1 d="50.1"


1-Общий ввод:

Входными данными этой функции могут быть все!

Определяет, является ли данная переменная числовой.Числовые строки состоят из необязательного знака, любого количества цифр, необязательной десятичной части и необязательной экспоненциальной части.Таким образом, +0123.45e6 является допустимым числовым значением.Шестнадцатеричный (например ,0xf4c3b00c) и двоичный (например,0b10100111001) обозначения не допускаются.

is_numeric является цифровым функция

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

что такое аст?


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

использование улица - цифра () способ

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

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

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

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

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

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

Это действительно поднимает интересный вопрос о том, что такое "число".Включаете ли вы "inf", который допустим как значение с плавающей точкой в 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

Я также использовал функцию, о которой вы упомянули, но вскоре я заметил, что такие строки, как "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
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

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

return True if str1.lstrip('-').replace('.','',1).isdigit() or float(str1) else False

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

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

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

Вы можете обобщить метод исключения полезным способом, возвращая больше полезных значений, чем True и False.Например, эта функция заключает строки в кавычки, но оставляет только числа.Это как раз то, что мне было нужно для быстрого и грязного фильтра, чтобы создать некоторые определения переменных для 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:]), ')'

Я работал над проблемой, которая привела меня к этой теме, а именно, как преобразовать набор данных в строки и числа наиболее интуитивно понятным способом.Прочитав исходный код, я понял, что то, что мне было нужно, отличалось двумя способами:

1 - Я хотел получить целочисленный результат, если строка представляла целое число

2 - Я хотел, чтобы число или строковый результат были вставлены в структуру данных

поэтому я адаптировал исходный код для создания этой производной:

def string_or_number(s):
    try:
        z = int(s)
        return z
    except ValueError:
        try:
            z = float(s)
            return z
        except ValueError:
            return s

Попробуй это.

 def is_number(var):
    try:
       if var == int(var):
            return True
    except Exception:
        return False

Вспомогательная функция пользователя:

def if_ok(fn, string):
  try:
    return fn(string)
  except Exception as e:
    return None

тогда

if_ok(int, my_str) or if_ok(float, my_str) or if_ok(complex, my_str)
is_number = lambda s: any([if_ok(fn, s) for fn in (int, float, complex)])

используйте следующее, оно обрабатывает все случаи:-

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')
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top