Python Forum
Determine if string is integer
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Determine if string is integer
#1
Got an assignment in my programming class that I'm having a hard time figuring out.
My teacher has created a .pyc file and it provides to me a variable. My task is to take the variable and determine if it is an integer or not.

I'm not allowed to use any "string" methods or try..except statements.
His one hint was that you will want a while loop that goes through each character of the "variable" and checks to see if it is legal. After that, it gets a little more complicated.
Also he says that it can be written in about 15 lines of code.

His pyc file goes through about 75 tests and I'm still failing on over half of them because all I can think of is nesting several If statements to check ordValues, but of course my code gets longer than 15 lines.

Some examples I'm having to evaluate are:
1.0 = True
-1 = True
1 = True (space in first position)
1.000013 = False
2341 134115 = False
+123 = True

Is anyone willing to give me some ideas on how I would do this as not being able to use string methods is really confusing me.

Thanks
Reply
#2
Can you show us what you've tried? We like to help you fix code rather than write it for you.
Craig "Ichabod" O'Brien - xenomind.com
I wish you happiness.
Recommended Tutorials: BBCode, functions, classes, text adventures
Reply
#3
from grader import grade_is_integer

def main():
    grade_is_integer(is_integer)

def is_integer(testValue):
    """Returns True if testValue is an integer and False otherwise."""

    isInteger = True
    
    testValue = str(testValue)
    length = len(testValue)
    count = 0
    while count < length:
        ordValue = ord(testValue[count])
        if ordValue >= 48 and ordValue <= 57:
            count = count + 1
        else:
            isInteger = False
            break
    
    return isInteger
    
main()
Reply
#4
I would check the strings directly, it makes the code clearer. I would also loop over the string directly, sort of like:

for char in testValue:
    if char in '1234567890':
        ....
That saves code on converting and keeping track of the loop. I would have a phase variable, so you can have a phase where you watch for white space or a preceding negative sign, and the change phase when checking for digits, and then a final phase for trailing white space.
Craig "Ichabod" O'Brien - xenomind.com
I wish you happiness.
Recommended Tutorials: BBCode, functions, classes, text adventures
Reply
#5
I observe that your teacher has unconventional definition of integer which is not aligned with Python:

>>> int('1.0')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: invalid literal for int() with base 10: '1.0'
>>> type(1.0)
<class 'float'>
It would have been pretty simple if there were integers. Floats make it more complicated.

I would try to get rid of + / - on left and .0 in right with indexes/slices and then return True or False with all():

>>> allowed = '0123456789'
>>> all(char in allowed for char in '123')
True
EDIT:

From provided test cases one can deduct following about 'integers':

- there might be empty space(s) before characters
- there might be + / - at the beginning
- one can assume that there might be empty space(s) followed by + / -
- there might be decimal places; if decimals are all zero then number is integer

Interestingly it can be done with exactly 15 lines of code:

def is_integer(s):
    allowed = '0123456789'                 # define allowed chars
    while True:                            # clean up string from empty spaces at the beginning and following + or -
        if s[0] == ' ':                    # if starts with empty space
            s = s[1:]                      # new value will be starting from second element
        else:                              # if not starting with empty space
            if s[0] in ['+', '-']:         # but starts with either + or -
                s = s[1:]                  # new value will be starting from second element
                break                      # break the loop as next must be character to be checked
            else:                          # if not starts with empty space or + / - 
                break                      # break the loop
    if '.' in s:                           # with cleaned s
        # return whether all before . are numbers and after are 0                           
        return all([all(char in allowed for char in s[:s.index('.')]), all(char == '0' for char in s[s.index('.') + 1:])])
    else: 
        # not float-like, return whether all are numbers
        return all(char in allowed for char in s)
Testing:

>>> lst = ['1.0', '-1', ' 1', '1.0000013', '2341 134115', '+123']
>>> [is_integer(item) for item in lst]
[True, True, True, False, False, True]
It will give IndexError if string is empty ('') or contains only spaces. If needed one needs to be defensive against that.
I'm not 'in'-sane. Indeed, I am so far 'out' of sane that you appear a tiny blip on the distant coast of sanity. Bucky Katt, Get Fuzzy

Da Bishop: There's a dead bishop on the landing. I don't know who keeps bringing them in here. ....but society is to blame.
Reply
#6
thanks for the replies.

We haven't covered the "all" function so I don't think I can use that.

and I'm not sure how just looking at only numbers get's me what I need because I as per my example, I have other characters I have to deal with. so the for x in .... statement initially provided I don't believe looks at everything necessary.

As I've been playing around with code some other hints have come out (ie everytime I fail on a test the teacher provides a hint back):
1 = True (space at end)
-- = False (double dash)

Ok so I figured out how to print my testValue to see all of the tests that my teacher is taking me through. Here are the 75 tests, some that I have passed some that I have failed:

Test 1: passed
-1
Test 2: passed
1
Test 3: passed
0
Test 4: passed
239485762349857623498576
Test 5: passed
0
Test 6: passed
1.0
Test 7: passed
0.0
Test 8: passed
0.0
Test 9: passed
0.0
Test 10: passed
-1.0
Test 11: passed
1.0
Test 12: passed
1.0
Test 13: passed
1
Test 14: passed
-1
Test 15: passed
+1
Test 16: passed
0
Test 17: passed
1
Test 18: passed
0
Test 19: passed
1
Test 20: FAILED
0
Test 21: FAILED
1
Test 22: passed
0
Test 23: passed
-01
Test 24: passed
23948576234985762345634563498576
Test 25: passed
0000000000000000
Test 26: passed
00000000008000001
Test 27: passed
1.000
Test 28: passed
121.
Test 29: passed
000000.
Test 30: passed
.000
Test 31: passed
00.000000
Test 32: passed
11.00000
Test 33: passed
-12.0000
Test 34: passed
-145.
Test 35: passed
+15.0000
Test 36: passed
+154000.
Test 37: passed
13.0000000000000000000000000000000000000000000
Test 38: passed
1.00013
Test 39: FAILED
0.000113
Test 40: FAILED
-0.000991
Test 41: FAILED
239485762 349857623498576
Test 42: passed

Test 43: passed
-
Test 44: FAILED
--
Test 45: FAILED
++
Test 46: FAILED
+
Test 47: FAILED
-+1
Test 48: FAILED
+--1
Test 49: FAILED
------1
Test 50: FAILED
++++1
Test 51: FAILED
one
Test 52: passed
7f
Test 53: passed
77777777f
Test 54: passed
f7
Test 55: passed
1...0
Test 56: FAILED
1..
Test 57: FAILED
.
Test 58: FAILED
..
Test 59: FAILED
....
Test 60: FAILED
...
Test 61: FAILED
...1
Test 62: FAILED
1.0.
Test 63: FAILED
1.0...
Test 64: FAILED
1.2
Test 65: FAILED
0.3
Test 66: FAILED
0.1.0.8
Test 67: FAILED
-0.18
Test 68: FAILED
.+0+
Test 69: FAILED
++--..00
Test 70: FAILED
None
Test 71: passed
[]
Test 72: passed
[1]
Test 73: passed
True
Test 74: passed
False
Test 75: passed
Reply
#7
Well working through elif statements I was able to get 100% solved, but I'm using a .strip() on my string conversion so technically not right, also longer that 15 lines, but at least it works. Not sure how to get rid of the leading spaces or trailing spaces otherwise. Here is my new code:
from grader import grade_is_integer

def main():
    grade_is_integer(is_integer)

def is_integer(testValue):
    """Returns True if testValue is an integer and False otherwise."""

    isInteger = True
    
    testValue = str(testValue).strip()
    length = len(testValue)
    count = 0
    decimalcount = 0
    if length == count:
        isInteger = False
    while count < length:
        ordValue = ord(testValue[count])
        if ordValue >= 48 and ordValue <= 57 and decimalcount == 0:
            count = count + 1
        elif ordValue >= 43 and ordValue <=45 and count == 0 and length != 1:
            count = count + 1
        elif ordValue == 46 and decimalcount == 0 and length != 1:
            count = count + 1
            decimalcount = decimalcount + 1
        elif decimalcount > 0 and ordValue == 48:
            count = count + 1
        else:
            isInteger = False
            break
        
    print(testValue)
    return isInteger
    
main()
Reply
#8
<vent>I hate assignments like this - do something that can be done efficiently and elegantly, but don't do it that way, do it in a manner no pro ever would. Let's teach bad technique.</vent>
Ok , that out of the way.
I hope the teacher lets you then approach the same problem with "weapons free" and challenges you to get under 5 lines.
Reply
#9
I know next to nothing what the 'integer' supposed to be. Test results are not that helpful because there are only pass/fail information and not information what result was expected. Can't help.

Therefore I make just some nitpicking about code:

- it is advisable to use conventions set in PEP8 - Naming Conventions - Function and Variable names

- some things in code can be expressed more concisely:

# instead of:
count = count + 1

# one can use:
count += 1

# instead of:
if ordValue >= 48 and ordValue <= 57

# one can use:
if ord_value in range(48, 58)
if 48 <= ord_value <= 57
- docstring should consist correct information. Currently there is '"""Returns True if testValue is an integer and False otherwise.""". This is not correct, as it considers floats as integers etc. You should not mislead yourself (and others who may read your code) that this function has something to do with Python integers and/or functionality provided by built-in int() function.
I'm not 'in'-sane. Indeed, I am so far 'out' of sane that you appear a tiny blip on the distant coast of sanity. Bucky Katt, Get Fuzzy

Da Bishop: There's a dead bishop on the landing. I don't know who keeps bringing them in here. ....but society is to blame.
Reply
#10
Short and simple:

def is_int(string):
    try:
        int(string)
    except ValueError:
        return False
    else:
        return True
The builtin function int has already an integrated parser for numbers and rules.
You can reimplenent the wheel or trust Python.
Almost dead, but too lazy to die: https://sourceserver.info
All humans together. We don't need politicians!
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Using an integer to manipulate a string/text variable rexyboy2121 1 1,748 Apr-22-2020, 01:37 AM
Last Post: michael1789
  Converting String to Integer Python Johnny1998 5 3,065 Aug-02-2019, 08:13 PM
Last Post: Johnny1998

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020