[Tutor] Python-list thread: int vs. float
Steven D'Aprano
steve at pearwood.info
Sat Feb 11 03:06:07 EST 2017
On Fri, Feb 10, 2017 at 07:59:04PM -0600, boB Stepp wrote:
> He cannot figure out how to reliably tell if the user's input is an
> integer, float or neither. So I thought I would come up with my
> solution, which currently is:
>
> py3: def ck_input():
> ... value_to_ck = input('Enter a number:')
> ... try:
> ... value = int(value_to_ck)
> ... print('You have entered an integer.')
> ... except ValueError:
> ... try:
> ... value = float(value_to_ck)
> ... print('You have entered a float.')
> ... except ValueError:
> ... print('You have failed to enter a numerical value.')
> ...
[...]
> This is all well and good. I am not trying to elicit an "Atta boy,
> boB!" here. ~(:>))
Nevertheless, atta boy boB!
The only not-so-good part of this is that you have mixed user-interface
and internal calculation. Better:
def to_number(string):
"""Convert string to either an int or a float, or raise ValueError."""
try:
return int(string)
except ValueError:
return float(string)
def check_input():
value_to_ck = input('Enter a number: ')
try:
value = to_number(value_to_ck)
except ValueError:
print('You have failed to enter a numerical value.')
return
if isinstance(value, float):
print('You have entered a float.')
else:
print('You have entered an int.')
This gives you nice separation between the function that interacts with
the user, and the function that does the actual conversion.
> Instead, I am wondering if there is something in
> Python's wonderful cornucopia of programming stuff that can simplify
> this type of check.
The most reliable and foolproof way of checking if something is a valid
int is to ask int to convert it, and see if it fails.
Likewise for floats, where the format is *very* complex. Any of these,
and many more, should be accepted:
1.2345
+1.2345
-1.2345e0
123.45e+20
123.45E-20
.123
-.123
+.123e-12
123.
inf
+inf
-inf
NaN
Getting all the gory details right of what is and isn't allowed may be
tricky, but that's okay, because float() already understands how to do
it for you.
> As you might guess from my earlier post this
> evening, I have been playing around with "type()" and "isinstance()",
> but if I try something like:
>
> py3: isinstance(int('5.0'))
> Traceback (most recent call last):
> File "<stdin>", line 1, in <module>
> ValueError: invalid literal for int() with base 10: '5.0'
The problem here is that int('5.0') raises an exception because '.' is
not a valid digit for integers, so it fails before isinstance() gets a
chance to run.
Valid digits for integers include 0 through 9 in decimal, plus no more
than one leading + or - sign, and whitespace (space, tabs, newlines)
before or after the string. If you specify the base, the set of valid
digits will change, e.g. int(string, 16) will allow 0 through 9 plus A
through F in lower and upper case.
But whatever base you choose, '.' is not a valid digit.
--
Steve
More information about the Tutor
mailing list