23

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?

Brad Solomon
  • 38,521
  • 31
  • 149
  • 235

11 Answers11

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)
francisco sollima
  • 7,952
  • 4
  • 22
  • 38
9

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"
Mohideen bin Mohammed
  • 18,813
  • 10
  • 112
  • 118
7

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
kjmerf
  • 4,275
  • 3
  • 21
  • 29
4

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.
srikavineehari
  • 2,502
  • 1
  • 11
  • 21
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.

Rafe
  • 1,937
  • 22
  • 31
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.

Samie Bencherif
  • 1,285
  • 12
  • 27
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.

jaquinocode
  • 634
  • 7
  • 12
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)```
AHMAD ZIA
  • 1
  • 1
  • Code-only answers like this are often down-voted here. Please [edit](https://stackoverflow.com/posts/65099721/edit) your answer and explain what you changed or how it works or something. – Arthur Pereira Dec 02 '20 at 23:30
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.

BBorisov95
  • 41
  • 9
0

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).

user-asterix
  • 826
  • 8
  • 12
-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
Morteza
  • 11
  • 3
  • This does not provide an answer to the question. Once you have sufficient [reputation](https://stackoverflow.com/help/whats-reputation) you will be able to [comment on any post](https://stackoverflow.com/help/privileges/comment); instead, [provide answers that don't require clarification from the asker](https://meta.stackexchange.com/questions/214173/why-do-i-need-50-reputation-to-comment-what-can-i-do-instead). - [From Review](/review/late-answers/31171035) – aaossa Mar 03 '22 at 15:36