Checking If a String Can Be Converted to Float in Python

Checking if a string can be converted to float in Python

I would just use..

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

..it's simple, and it works. Note that it will still throw OverflowError if element is e.g. 1<<1024.

Another option would be a regular expression:

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

How do I check if a string represents a number (float or int)?

Which, not only is ugly and slow

I'd dispute both.

A regex or other string parsing method would be uglier and slower.

I'm not sure that anything much could be faster than the above. It calls the function and returns. Try/Catch doesn't introduce much overhead because the most common exception is caught without an extensive search of stack frames.

The issue is that any numeric conversion function has two kinds of results

  • A number, if the number is valid
  • A status code (e.g., via errno) or exception to show that no valid number could be parsed.

C (as an example) hacks around this a number of ways. Python lays it out clearly and explicitly.

I think your code for doing this is perfect.

Is there built-in way to check if string can be converted to float?

As stated by and Macattack and Jab, you could use try except, which you can read about in python's docs or w3school's tutorial.

Try Except clauses have the form:

try:
# write your code
pass
except Exception as e: # which can be ValueError, or other's exceptions
# deal with Exception, and it can be called using the variable e
print(f"Exception was {e}") # python >= 3.7
pass
except Exception as e: # for dealing with other Exception
pass
# ... as many exceptions you would need to handle
finally:
# do something after dealing with the Exception
pass

For a list of built-in Exceptions, see python's docs.

How do I parse a string to a float or int?

>>> a = "545.2222"
>>> float(a)
545.22220000000004
>>> int(float(a))
545

Checking to see if a string is an integer or float

If the string is convertable to integer, it should be digits only. It should be noted that this approach, as @cwallenpoole said, does NOT work with negative inputs beacuse of the '-' character. You could do:

if NumberString.isdigit():
Number = int(NumberString)
else:
Number = float(NumberString)

If you already have Number confirmed as a float, you can always use is_integer (works with negatives):

if Number.is_integer():
Number = int(Number)

Fast checking if a string can be converted to float or int in python

All generalizations are false (irony intended). One cannot say that try: except: is always faster than regex or vice versa. In your case, regex is not overkill and would be much faster than the try: except: method. However, based on our discussions in the comments section of your question, I went ahead and implemented a C library that efficiently performs this conversion (since I see this question a lot on SO); the library is called fastnumbers. Below are timing tests using your try: except: method, using regex, and using fastnumbers.


from __future__ import print_function
import timeit

prep_code = '''\
import random
import string
x = [''.join(random.sample(string.ascii_letters, 7)) for _ in range(10)]
y = [str(random.randint(0, 1000)) for _ in range(10)]
z = [str(random.random()) for _ in range(10)]
'''

try_method = '''\
def converter_try(vals):
resline = []
for item in vals:
try:
resline.append(int(item))
except ValueError:
try:
resline.append(float(item))
except ValueError:
resline.append(item)

'''

re_method = '''\
import re
int_match = re.compile(r'[+-]?\d+$').match
float_match = re.compile(r'[-+]?\d*\.?\d+(?:[eE][-+]?\d+)?$').match
def converter_re(vals):
resline = []
for item in vals:
if int_match(item):
resline.append(int(item))
elif float_match(item):
resline.append(float(item))
else:
resline.append(item)

'''

fn_method = '''\
from fastnumbers import fast_real
def converter_fn(vals):
resline = []
for item in vals:
resline.append(fast_real(item))

'''

print('Try with non-number strings', timeit.timeit('converter_try(x)', prep_code+try_method), 'seconds')
print('Try with integer strings', timeit.timeit('converter_try(y)', prep_code+try_method), 'seconds')
print('Try with float strings', timeit.timeit('converter_try(z)', prep_code+try_method), 'seconds')
print()
print('Regex with non-number strings', timeit.timeit('converter_re(x)', prep_code+re_method), 'seconds')
print('Regex with integer strings', timeit.timeit('converter_re(y)', prep_code+re_method), 'seconds')
print('Regex with float strings', timeit.timeit('converter_re(z)', prep_code+re_method), 'seconds')
print()
print('fastnumbers with non-number strings', timeit.timeit('converter_fn(x)', prep_code+fn_method), 'seconds')
print('fastnumbers with integer strings', timeit.timeit('converter_fn(y)', prep_code+fn_method), 'seconds')
print('fastnumbers with float strings', timeit.timeit('converter_fn(z)', prep_code+fn_method), 'seconds')
print()

The output looks like this on my machine:

Try with non-number strings 55.1374599934 seconds
Try with integer strings 11.8999788761 seconds
Try with float strings 41.8258318901 seconds

Regex with non-number strings 11.5976541042 seconds
Regex with integer strings 18.1302199364 seconds
Regex with float strings 19.1559209824 seconds

fastnumbers with non-number strings 4.02173805237 seconds
fastnumbers with integer strings 4.21903610229 seconds
fastnumbers with float strings 4.96900391579 seconds

A few things are pretty clear

  • try: except: is very slow for non-numeric input; regex beats that handily
  • try: except: becomes more efficient if exceptions don't need to be raised
  • fastnumbers beats the pants off both in all cases

So, if you don't want to use fastnumbers, you need to assess if you are more likely to encounter invalid strings or valid strings, and base your algorithm choice on that.

How can I check if a string represents an int, without using try/except?

If you're really just annoyed at using try/excepts all over the place, please just write a helper function:

def RepresentsInt(s):
try:
int(s)
return True
except ValueError:
return False

>>> print RepresentsInt("+123")
True
>>> print RepresentsInt("10.0")
False

It's going to be WAY more code to exactly cover all the strings that Python considers integers. I say just be pythonic on this one.



Related Topics



Leave a reply



Submit