-2

I am a beginner in python and I am currently working on a calculator not like this: Enter Something: add "Enter 1 number : 1" "Enter 2 number : 3" The answer is 5 not like that or using eval() I Want to create a calculator where they input something like this: "add 1 3" and output should be 4. but I have to check that the first word is a string 2nd is a integer or float and 3rd is also number I have created a script but I have one problem that I don't know how to check if the input is a integer or string or float I have used isdigit() it works but it doesn't count negative numbers and float as a number I have also used isinstance() but it doesn't work and thinks that the input is a integer even when its a string and I don't know how to use the try and except method on this script

while True:
    exitcond = ["exit","close","quit"]
    operators =["add","subtract","multiply","divide"]
    uinput = str(input())
    lowereduin = uinput.lower()
    splited = lowereduin.split(" ")
    if lowereduin in exitcond:
        break
    if splited[0] == operators[0]:
        if isinstance(splited[1],int) == True:
            if isinstance(splited[2] , int) == True:
                result = int(splited[1]) + int(splited[2])
                print(result)
            else:
                print("enter a number")
        else:
            print("enter a number")

and when I run this script and type add 1 3 its says enter a number and when I only type add its give this error

Traceback (most recent call last):
  File "C:\Users\Tyagiji\Documents\Python Projects\TRyinrg differet\experiments.py", line 11, in <module>
    if isinstance(splited[1],int) == True:
IndexError: list index out of range

Can someone tell me what's this error and if this doesn't work can you tell me how to use try: method on this script.

shafee
  • 15,566
  • 3
  • 19
  • 47
  • the error shows that you have not given correct input. Correct input should be `add 1 2` have you given this input ? – Deepak Tripathi Oct 15 '22 at 07:23
  • `isinstance(splited[1],int) == True` will always fail as you've split a string, so `splited[1]` is never an integer. Also the `==True` is redundant. – bn_ln Oct 15 '22 at 07:26
  • @DeepakTripathi yes i typed this it says "enter a number" – Nishesh Tyagi Oct 15 '22 at 07:27
  • @bn_ln so what can I I do instead of splitting the string and I have also tried ```if isinstance(splited[1],int): ``` – Nishesh Tyagi Oct 15 '22 at 07:30
  • Just remove the `str()` typecaste from the line `uinput = str(input())` and now try `uinput.isdigit()` and `uinput.isfloat()` – Swagrim Oct 15 '22 at 07:34
  • @Swagrim removed the ``str()`` and i tried ```uinput.isdigit()``` and it works but it doesn't count negative numbers and float. – Nishesh Tyagi Oct 15 '22 at 07:37

2 Answers2

0

You can try the following approach and play with type checking

import operator

while True:
    exitcond = ["exit","close","quit"]
    operators ={"add": operator.add,"subtract":operator.sub,"multiply": operator.mul,"divide":operator.truediv}
    uinput = str(input())
    lowereduin = uinput.lower()
    splited = lowereduin.split(" ")
    if lowereduin in exitcond or (len(splited) !=3):
        break
    try:
        if splited[0] not in operators.keys():
            raise ValueError(f"{splited[0]} not in {list(operators.keys())}")
        op = operators.get(splited[0])
        val = op(
            *map(int, splited[1:])
        )
        print(val)
    except (ValueError, ZeroDivisionError) as err:
        print(err)
        break
Deepak Tripathi
  • 3,175
  • 1
  • 8
  • 21
  • I tried this and typed add 1 2 it says ```add not in ['add', 'subtract', 'multiply', 'divide']``` – Nishesh Tyagi Oct 15 '22 at 07:40
  • Yes, this answer has a bug in it. Change `if op not in operators:` to `if not op:` – bn_ln Oct 15 '22 at 07:44
  • I have changed it , Now check @NisheshTyagi . The condition should be before getting the operator – Deepak Tripathi Oct 15 '22 at 07:44
  • you should really test your answer before posting it – bn_ln Oct 15 '22 at 07:45
  • 1
    @bn_ln Sorry for that , I have tested for failure cases thatwhy success test cases skipped. – Deepak Tripathi Oct 15 '22 at 07:48
  • @DeepakTripathi when i type add 1 3 it works like it did with ```isdigit()``` but it doesnt work for float it gives ```invalid literal for int() with base 10: '1.6'``` it gives the same for a string ```invalid literal for int() with base 10: 'b'``` it should give "please enter a number" – Nishesh Tyagi Oct 15 '22 at 07:49
  • For that only , I have said you can play with data type, `map(int, splited[1:])` to `map(float, splitted[1:])` . – Deepak Tripathi Oct 15 '22 at 07:53
0

Building on Deepak's answer. A dictionary of operator names to functions is a good approach. And you can add to splits until you have enough numbers to proceed.

import operator as op
while True:
    exitcond = ["exit","close","quit"]
    operators = {"add": op.add,"subtract": op.sub, "multiply": op.mul, "divide": op.truediv}
    splits = str(input()).lower().split()
    if any(part in exitcond for part in splits):
        break

    while len(splits) < 3:
        splits.append(input('Enter number: '))

    try:
        print(operators[splits[0]](*map(lambda x: float(x.replace(',','')), splits[1:3])))
    except ZeroDivisionError:
        print("Can't divide by 0")
    except:
        print('Expected input: add|subtract|multiply|divide [number1] [number2] -- or -- exit|quit|close')

Things to note, the lambda function removes all commas , as they fail for floats, and then converts the all number strings to floats. So, the answer will always be a float, which opens the can of worms that add 1.1 2.2 won't be exactly 3.3 due to the well documented issues with floating point arithmatic and computers

bn_ln
  • 1,648
  • 1
  • 6
  • 13