Using isdigit for floats?
Question:
a = raw_input('How much is 1 share in that company? ')
while not a.isdigit():
print("You need to write a number!n")
a = raw_input('How much is 1 share in that company? ')
This only works if the user enters an integer
, but I want it to work even if they enter a float
, but not when they enter a string
.
So the user should be able to enter both 9
and 9.2
, but not abc
.
How should I do it?
Answers:
EAFP
try:
x = float(a)
except ValueError:
print("You must enter a number")
Use regular expressions.
import re
p = re.compile('d+(.d+)?')
a = raw_input('How much is 1 share in that company? ')
while p.match(a) == None:
print "You need to write a number!n"
a = raw_input('How much is 1 share in that company? ')
I think @dan04 has the right approach (EAFP), but unfortunately the real world is often a special case and some additional code is really required to manage thingsāso below is a more elaborate, but also a bit more pragmatic (and realistic):
import sys
while True:
try:
a = raw_input('How much is 1 share in that company? ')
x = float(a)
# validity check(s)
if x < 0: raise ValueError('share price must be positive')
except ValueError, e:
print("ValueError: '{}'".format(e))
print("Please try entering it again...")
except KeyboardInterrupt:
sys.exit("n<terminated by user>")
except:
exc_value = sys.exc_info()[1]
exc_class = exc_value.__class__.__name__
print("{} exception: '{}'".format(exc_class, exc_value))
sys.exit("<fatal error encountered>")
else:
break # no exceptions occurred, terminate loop
print("Share price entered: {}".format(x))
Sample usage:
> python numeric_input.py
How much is 1 share in that company? abc
ValueError: 'could not convert string to float: abc'
Please try entering it again...
How much is 1 share in that company? -1
ValueError: 'share price must be positive'
Please try entering it again...
How much is 1 share in that company? 9
Share price entered: 9.0
> python numeric_input.py
How much is 1 share in that company? 9.2
Share price entered: 9.2
The existing answers are correct in that the more Pythonic way is usually to try...except
(i.e. EAFP).
However, if you really want to do the validation, you could remove exactly 1 decimal point before using isdigit()
.
>>> "124".replace(".", "", 1).isdigit()
True
>>> "12.4".replace(".", "", 1).isdigit()
True
>>> "12..4".replace(".", "", 1).isdigit()
False
>>> "192.168.1.1".replace(".", "", 1).isdigit()
False
Notice that this does not treat floats any different from ints however. You could add that check if you really need it though.
s = '12.32'
if s.replace('.', '').replace('-', '').isdigit():
print(float(s))
Note that this will work for negative float
s as well.
Building on dan04’s answer:
def isDigit(x):
try:
float(x)
return True
except ValueError:
return False
usage:
isDigit(3) # True
isDigit(3.1) # True
isDigit("3") # True
isDigit("3.1") # True
isDigit("hi") # False
import re
string1 = "0.5"
string2 = "0.5a"
string3 = "a0.5"
string4 = "a0.5a"
p = re.compile(r'd+(.d+)?$')
if p.match(string1):
print(string1 + " float or int")
else:
print(string1 + " not float or int")
if p.match(string2):
print(string2 + " float or int")
else:
print(string2 + " not float or int")
if p.match(string3):
print(string3 + " float or int")
else:
print(string3 + " not float or int")
if p.match(string4):
print(string4 + " float or int")
else:
print(string4 + " not float or int")
output:
0.5 float or int
0.5a not float or int
a0.5 not float or int
a0.5a not float or int
The provided answers fail if the string contains some special characters such as underscore (e.g. ‘1_1’). The following function returns correct answer in all case that I tested.
def IfStringRepresentsFloat(s):
try:
float(s)
return str(float(s)) == s
except ValueError:
return False
a = raw_input('How much is 1 share in that company? ')
while not a.isdigit():
print("You need to write a number!n")
a = raw_input('How much is 1 share in that company? ')
This only works if the user enters an integer
, but I want it to work even if they enter a float
, but not when they enter a string
.
So the user should be able to enter both 9
and 9.2
, but not abc
.
How should I do it?
EAFP
try:
x = float(a)
except ValueError:
print("You must enter a number")
Use regular expressions.
import re
p = re.compile('d+(.d+)?')
a = raw_input('How much is 1 share in that company? ')
while p.match(a) == None:
print "You need to write a number!n"
a = raw_input('How much is 1 share in that company? ')
I think @dan04 has the right approach (EAFP), but unfortunately the real world is often a special case and some additional code is really required to manage thingsāso below is a more elaborate, but also a bit more pragmatic (and realistic):
import sys
while True:
try:
a = raw_input('How much is 1 share in that company? ')
x = float(a)
# validity check(s)
if x < 0: raise ValueError('share price must be positive')
except ValueError, e:
print("ValueError: '{}'".format(e))
print("Please try entering it again...")
except KeyboardInterrupt:
sys.exit("n<terminated by user>")
except:
exc_value = sys.exc_info()[1]
exc_class = exc_value.__class__.__name__
print("{} exception: '{}'".format(exc_class, exc_value))
sys.exit("<fatal error encountered>")
else:
break # no exceptions occurred, terminate loop
print("Share price entered: {}".format(x))
Sample usage:
> python numeric_input.py
How much is 1 share in that company? abc
ValueError: 'could not convert string to float: abc'
Please try entering it again...
How much is 1 share in that company? -1
ValueError: 'share price must be positive'
Please try entering it again...
How much is 1 share in that company? 9
Share price entered: 9.0
> python numeric_input.py
How much is 1 share in that company? 9.2
Share price entered: 9.2
The existing answers are correct in that the more Pythonic way is usually to try...except
(i.e. EAFP).
However, if you really want to do the validation, you could remove exactly 1 decimal point before using isdigit()
.
>>> "124".replace(".", "", 1).isdigit()
True
>>> "12.4".replace(".", "", 1).isdigit()
True
>>> "12..4".replace(".", "", 1).isdigit()
False
>>> "192.168.1.1".replace(".", "", 1).isdigit()
False
Notice that this does not treat floats any different from ints however. You could add that check if you really need it though.
s = '12.32'
if s.replace('.', '').replace('-', '').isdigit():
print(float(s))
Note that this will work for negative float
s as well.
Building on dan04’s answer:
def isDigit(x):
try:
float(x)
return True
except ValueError:
return False
usage:
isDigit(3) # True
isDigit(3.1) # True
isDigit("3") # True
isDigit("3.1") # True
isDigit("hi") # False
import re
string1 = "0.5"
string2 = "0.5a"
string3 = "a0.5"
string4 = "a0.5a"
p = re.compile(r'd+(.d+)?$')
if p.match(string1):
print(string1 + " float or int")
else:
print(string1 + " not float or int")
if p.match(string2):
print(string2 + " float or int")
else:
print(string2 + " not float or int")
if p.match(string3):
print(string3 + " float or int")
else:
print(string3 + " not float or int")
if p.match(string4):
print(string4 + " float or int")
else:
print(string4 + " not float or int")
output:
0.5 float or int
0.5a not float or int
a0.5 not float or int
a0.5a not float or int
The provided answers fail if the string contains some special characters such as underscore (e.g. ‘1_1’). The following function returns correct answer in all case that I tested.
def IfStringRepresentsFloat(s):
try:
float(s)
return str(float(s)) == s
except ValueError:
return False