Checking to see if a string is an integer or float
Asked Answered
F

12

25

So I'm creating a program to show number systems, however I've run into issues at the first hurdle. The program will take a number from the user and then use that number throughout the program in order to explain several computer science concepts.

When explaining my first section, number systems, the program will say what type of number it is. I'm doing this by converting the string into a float number. If the float number only has '.0' after it then it converts it into a integer.

Currently I'm using this code

while CorrectNumber == False:
try:
    Number = float(NumberString) - 0
    print (Number)
except:
    print ("Error! Not a number!")

This is useful as it shows if the user has entered a number or not. However I am unsure how to now check the value after the decimal place to check if I should convert it into a integer or not. Any tips?

Fred answered 9/10, 2017 at 13:32 Comment(1)
S
21

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)
Slaty answered 9/10, 2017 at 13:44 Comment(2)
Does not apply to negative numbers.Masteratarms
Use int(NumberString) (in a try and handle ValueError) rather than using .isdigit, to check whether a string can be parsed as an int.Acervate
Y
8

Not sure I follow the question but here is an idea:

test = ['1.1', '2.1', '3.0', '4', '5', '6.12']

for number in test:
    try:
        print(int(number))
    except ValueError:
        print(float(number))

Returns:

1.1
2.1
3.0
4
5
6.12
Your answered 9/10, 2017 at 13:41 Comment(10)
Please don't encourage writing except: without specifying some exception type. It should be except ValueError:Acervate
This is the better, more Pythonic approach.Masteratarms
How does this work? could you point to some documentation?Hughes
I don't like this technique. You're playing with try except like it's the normal execution of your program. It's misleading.Jala
@Autechre: Exception catching is in fact normal execution flow in Python. The standard for loop is built on exceptions. The entire async system is built on exceptions. hasattr is built on exceptions. Where other languages might provide "tryParseInt" and "tryParseFloat" functions that return an "optional" wrapper, the standard way to check whether something can be parsed as an int or a float in Python is to just try it and catch the exception if it fails.Pianism
People keep mistaking methods like isdigit for the right tool because they expect Python not to be like this, but isdigit, isdecimal, and isnumeric are really Unicode character property checks, not tests for whether a string represents a number. It's extremely rare for those methods to be the right tool for a job.Pianism
@Pianism according to Python documentation : "Errors detected during execution are called exceptions and are not unconditionally fatal" "Most exceptions are not handled by programs". Semantically, an exception is understood as an error. If you play with exceptions in your program to code the normal behaviour of your program, it can be puzzling for another programmer to understand the program raising an exception has a totally normal behaviour. I've worked on many projects and I almost never see code using exception for the normal behaviour of a program. Using exception like this is unusualJala
@Autechre: Those quotes are from the tutorial, which glosses over a lot of details in favor of trying to get newbies acquainted with the basics. Most exceptions that newbies will see, they should not catch, and most possible exceptions should not be caught, but most exceptions that occur in practice are caught. If we're pointing at docs, I can point at the EAFP glossary entry, which describes it as a "common Python coding style" and "clean and fast".Pianism
Frankly, I don't think EAFP style is actually common these days, even in Python. But even if you don't like EAFP, you have to realize when an interface was designed for EAFP coding. The design of int and float was designed for EAFP. Mistaking the design for an LBYL design is how we get people constantly writing buggy misuses of isdigit. If you don't like EAFP, you can write your own "tryParseInt" wrapper that returns None on failure, so you only have to write the exception handling once.Pianism
@Pianism My bad ! I didn't know this EAFP idiom existed ! I've been doing Python since a long time and I never saw this. That's crazy...Jala
P
8

Here is the method to check,

a = '10'
if a.isdigit():
   print "Yes it is Integer"
elif a.replace('.','',1).isdigit() and a.count('.') < 2:
   print "Its Float"
else:
   print "Its is Neither Integer Nor Float! Something else"
Purdy answered 22/4, 2019 at 12:44 Comment(0)
B
6

This checks if the fractional-part has any non-zero digits.

def is_int(n):
    try:
        float_n = float(n)
        int_n = int(float_n)
    except ValueError:
        return False
    else:
        return float_n == int_n

def is_float(n):
    try:
        float_n = float(n)
    except ValueError:
        return False
    else:
        return True

Testing the functions:

nums = ['12', '12.3', '12.0', '123.002']

for num in nums:
    if is_int(num):
        print(num, 'can be safely converted to an integer.')
    elif is_float(num):
        print(num, 'is a float with non-zero digit(s) in the fractional-part.')

It prints:

12 can be safely converted to an integer.
12.3 is a float with non-zero digit(s) in the fractional-part.
12.0 can be safely converted to an integer.
123.002 is a float with non-zero digit(s) in the fractional-part.
Balfore answered 9/10, 2017 at 14:40 Comment(0)
C
1

Regular expressions are nice for this as they can be custom tailored in case you have some edge-cases. For example:

  • How do you want to handle padded numbers (numbers with leading zeros). My example here includes this consideration.
  • Do you need to handle exponents, e.g. 2.3E12 or 2.3e12. This is not handled here.

...in other words, if your implementation doesn't agree with an assumption mine makes, you can change it.

Regular expressions work in all versions of Python (and other languages). They can be compiled for reuse, so should be pretty quick.

# Int is:
#  - Only numbers that do NOT start with 0 (protect padded number strings)
#  - Exactly 0
re_int = re.compile(r"(^[1-9]+\d*$|^0$)")

# Float is:
#  - Only numbers but with exactly 1 dot.
#  - The dot must always be followed number numbers
re_float = re.compile(r"(^\d+\.\d+$|^\.\d+$)")

These tests all pass:

def test_re_int(self):
    self.assertTrue(re_int.match("1"))
    self.assertTrue(re_int.match("1543"))
    self.assertTrue(re_int.match("0"))  # Exactly 0 is good

    self.assertFalse(re_int.match("1.54"))
    self.assertFalse(re_int.match("1a4"))
    self.assertFalse(re_int.match("14a"))
    self.assertFalse(re_int.match("a14"))
    self.assertFalse(re_int.match("00"))  # Ambiguous
    self.assertFalse(re_int.match("0012"))  # Protect padding

def test_re_float(self):

    self.assertTrue(re_float.match("1.0"))
    self.assertTrue(re_float.match("1.456"))
    self.assertTrue(re_float.match("567.456"))
    self.assertTrue(re_float.match("0.10"))
    self.assertTrue(re_float.match(".10"))

    self.assertFalse(re_float.match("1.0.0"))  # Too many dots
    self.assertFalse(re_float.match(".10.0"))
    self.assertFalse(re_float.match("..034"))

    self.assertFalse(re_float.match("1"))
    self.assertFalse(re_float.match("0"))
    self.assertFalse(re_float.match("1a4"))
    self.assertFalse(re_float.match("14a"))
    self.assertFalse(re_float.match("a14"))

    self.assertFalse(re_float.match("1.a4"))
    self.assertFalse(re_float.match("1.4a"))
    self.assertFalse(re_float.match(".a14"))

Please comment if there are any caveats, missing details or regular expression improvements I can make.

Casimir answered 31/10, 2021 at 21:54 Comment(1)
It doesn’t handle negative values. If possible, please update.Parkin
M
1

However I am unsure how to now check the value after the decimal place to check if I should convert it into a integer or not.

Amazingly, everyone seemed to miss that this is a modulus question.

a = "3.0"
x = float(a)
if x % 1 == 0:
    print("It's an integer.")

At least, that's what I think you meant.

Modification answered 6/7, 2023 at 18:43 Comment(0)
F
1

Simple function that takes most cases into consideration:

def checking(val):
    if type(val) == bool:
        return 'bool'
    dType = 'str'
    try:
        float(val)         
        dType = 'float'    
        if str(int(val)) == str(val):          
            dType = 'int'      
    except:                     
        pass
    return (dType)        
 

Testing

for item in [0, 1,'1',-1,'-1',True, False, 'True','False', 'string', 0.0,'0.0',1.0, '1.0',1.3, '1.3',-1.3, '-1.3','2.3E12','-2.3E12']:
    print (item,': ', checking(item)) 

Printout:

    0 :  int
    1 :  int
    1 :  int
   -1 :  int
   -1 :  int
   True :  bool
   False :  bool
   True :  str
   False :  str
   string :  str
   0.0 :  float
   0.0 :  float
   1.0 :  float
   1.0 :  float
   1.3 :  float
   1.3 :  float
   -1.3 :  float
   -1.3 :  float
   2.3E12 :  float
  -2.3E12 :  float

Logic for checking function is simple. If a string is truly non-numeric (not float or int) then it cannot be cast to float and an exception is thrown and an 'str' is returned. If it is numeric then by default it can be cast to float. Once it is cast to float then we need to check that this numeric is a true int. Thus we check if it truly int (by casting to str to compare its string footprint).

Floating answered 7/8, 2023 at 17:12 Comment(0)
A
0

Here's my gist that not only checks for positive & negative ints, but also checks for positive & negative floats. It also checks if the string is just a normal non-number.

def int_float_or_string(string):
    try:
        int(string)  # strict and nice
    except ValueError:
        if is_strictly_float(string): # float() is too permissive, this is better
            return "float"
        else:
            return "string"
    else:
        return "int"

def is_strictly_float(string):
    if string.startswith("-"):
        string = string[1:]
    return "." in string and string.replace(".", "", 1).isdecimal()

int() is great for checking an integer, but float() has a problem of being too laid back in what it calls a float.

Ailin answered 14/5, 2020 at 5:28 Comment(0)
D
0
x=input("Enter a value to check it's  type: ")
def checknumber(a):
    try:
        a=float(a)
        if int(a)/a==1:
            print("This is Integer")
            return a
        elif a/int(a)>1:
            print("This is Float")
            return a
    except ValueError:
        print("This value is String")
        return str(a)
x=checknumber(x)```
Dosh answered 2/12, 2020 at 22:59 Comment(1)
Code-only answers like this are often down-voted here. Please edit your answer and explain what you changed or how it works or something.Reneerenegade
I
0

Kinda late, but I do use this method, whenever I must check if there is int or float digits/numbers in a string.

import re

def float_or_int_checker(el: str) -> bool:
    pattern = r'^[-+]?(\d+(\.\d*)?|\.\d+)$'
    if re.match(pattern, el):
        return True
    return False


l = ['3.14', '9', '', ' ', 3.14, 9, '3.14f', 'g9']
for i in l:
    print(float_or_int_checker(str(i)))
#output:
3.14: True
9: True
: False
: False
3.14: True
9: True
3.14f: False
g9: False

The regex pattern finds:

^[-+]? -> Checks if the string starts with minus or plus sign. The "?" makes this match optional

\d+(\.\d*)? -> Checks for one or more digits, the dot "." followed by any number is optional as weel.

\.\d+ -> Makes sure that if there is a decimal points it is followed by at least one digit.

Informer answered 6/7, 2023 at 18:19 Comment(0)
C
0
try:
    # convert to float if numeric
    n = float(n)
    # convert to int if it's the same
    if int(n) == n:
        n = int(n)
except ValueError:
    pass # n is a string
Cloakroom answered 6/12, 2023 at 11:8 Comment(0)
T
-1

I rewrite bin Mohammed's answer as follows (number also may be negative):

from numpy import nan, isnan

def is_valid_number(s):
    if (s.find('-') <= 0) and s.replace('-', '', 1).isdigit():
        if (s.count('-') == 0):
            s_type = 'Positive Integer'
        else:
            s_type = 'Negative Integer'
    elif (s.find('-') <= 0) and (s.count('.') < 2) and \
         (s.replace('-', '', 1).replace('.', '', 1).isdigit()):
        if (s.count('-') == 0):
            s_type = 'Positive Float'
        else:
            s_type = 'Negative Float'
    else:
        s_type = "Not alphanumeric!"
    return('{}\t is {}'.format(s, s_type))

example:

nums = ['12', '-34', '12.3', '-12.0', '123.0-02', '12!','5-6', '3.45.67']
for num in nums:
    print(is_valid_number(num))

result:

12   is Positive Integer
-34  is Negative Integer
12.3     is Positive Float
-12.0    is Negative Float
123.0-02     is Not alphanumeric!
12!  is Not alphanumeric!
5-6  is Not alphanumeric!
3.45.67  is Not alphanumeric!

minimal code:

from numpy import nan, isnan

def str2num(s):
    if (s.find('-') <= 0) and s.replace('-', '', 1).isdigit():
        return(int(s))
    elif (s.find('-') <= 0) and (s.count('.') < 2) and \
         (s.replace('-', '', 1).replace('.', '', 1).isdigit()):
        return(float(s))
    else:
        return(nan)

example:

nums = ['12', '-34', '12.3', '-12.0', '123.0-02', '12!','5-6', '3.45.67']
for num in nums:
    x = str2num(num)
    if not isnan(x):
        print('x =', x) # .... or do something else

result:

x = 12
x = -34
x = 12.3
x = -12.0
Taryn answered 27/2, 2022 at 10:56 Comment(1)
This does not provide an answer to the question. Once you have sufficient reputation you will be able to comment on any post; instead, provide answers that don't require clarification from the asker. - From ReviewReconstruct

© 2022 - 2024 — McMap. All rights reserved.