Вопрос-Ответ

Checking if a string can be converted to float in Python [duplicate]

Проверка, может ли строка быть преобразована в float в Python

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

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)

Это работает, но, очевидно, оператор if для этого немного медлителен. Другое решение, которое я рассмотрел, - это просто обернуть преобразование в блок try / catch и посмотреть, удастся ли оно, как описано в этом вопросе .

У кого-нибудь есть другие идеи? Мнения об относительных достоинствах раздела и подходах try / catch?

Переведено автоматически
Ответ 1

Я бы просто использовал..

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

..это просто и работает. Обратите внимание, что он все равно выдаст OverflowError, если элемент равен, например, 1<<1024.

Другим вариантом может быть регулярное выражение:

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

Метод Python3 для проверки float:

def is_float(element: any) -> bool:
#If you expect None to be passed:
if element is None:
return False
try:
float(element)
return True
except ValueError:
return False

Версия Python2 из приведенного выше: Как мне разобрать строку в float или int?

Всегда проводите модульное тестирование. Что является float, а что нет, может вас удивить:

Command to parse                        Is it a float?  Comment
-------------------------------------- --------------- ------------
print(isfloat("")) False
print(isfloat("1234567")) True
print(isfloat("1_2_3.4")) True 123.4, underscores ignored
print(isfloat("NaN")) True nan is also float
print(isfloat("123.456")) True
print(isfloat("123.E4")) True
print(isfloat(".1")) True
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("1,234")) False
print(isfloat("NULL")) False case insensitive
print(isfloat("NaNananana BATMAN")) False
print(isfloat(",1")) False
print(isfloat("123.EE4")) False
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

Пропускать исключения, подобные этому, плохо, потому что убивать канареек плохо, потому что метод float может завершиться неудачей по причинам, отличным от пользовательского ввода. Не используйте подобный код в критически важном программном обеспечении. Также python изменил свой контракт относительно того, какие строки unicode могут быть переведены в float, поэтому ожидайте, что это поведение этого кода изменится при основных обновлениях версии.

Ответ 3
'1.43'.replace('.','',1).isdigit()

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


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

вернет false


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

вернет false

Ответ 4

TL; DR:


  • Если ваши входные данные в основном представляют собой строки, которые могут быть преобразованы в float, то try: except: метод является лучшим собственным методом Python.

  • Если ваши входные данные в основном представляют собой строки, которые не могут быть преобразованы в float, лучше использовать регулярные выражения или метод partition .

  • Если вы 1) не уверены в своем вводе или вам нужно больше скорости и 2) не возражаете и можете установить стороннее расширение C, fastnumbers работает очень хорошо.


Существует другой метод, доступный через сторонний модуль под названием fastnumbers (раскрытие информации, я автор); он предоставляет функцию под названием isfloat . Я взял самый простой пример, описанный Джейкобом Габриэлсоном в этом ответе, но добавил fastnumbers.isfloat метод. Я должен также отметить, что пример Джейкоба не соответствовал параметру regex должным образом, потому что большая часть времени в этом примере была потрачена на глобальный поиск из-за оператора dot ... Я модифицировал эту функцию, чтобы дать более справедливое сравнение с 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 метод вполне хорош.

python string