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 handilytry: except:
becomes more efficient if exceptions don't need to be raisedfastnumbers
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/except
s 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
I Have a Problem with Sending Mail:Typeerror: _Init_() Got an Unexpected Keyword Argument 'Context'
Handling Spreadsheet Data Through the Clipboard in Gtk
Use Df Command to Show Only the %Used
What Is the Correct Way to Include Localisation in Python Packages
Pip Install MySQL-Python Fails with Environmenterror: MySQL_Config Not Found
Differencebetween Dict.Items() and Dict.Iteritems() in Python2
What Is the Most Efficient Way to Loop Through Dataframes with Pandas
Is There a Simple Way to Delete a List Element by Value
How to Create a Constant in Python
Beyond Top Level Package Error in Relative Import
How to Run Multiple Python Versions on Windows
Constantly Print Subprocess Output While Process Is Running
Filter Dict to Contain Only Certain Keys
How to Urlencode a Querystring in Python
Converting a String Representation of a List into an Actual List Object
Replace Values in a Pandas Series via Dictionary Efficiently