2
\$\begingroup\$

I decided to make a calculator as a project. Implementing basic addition, subtraction, division, and multiplication was fairly easy.

I wanted to add more functionality so I decided to implement a list of results the user view. However, I had a difficult time keeping track of the results numerically. I wrote a maze of if statements that are functional but seem to be overwrought with code. I am sure there is a better way to handle this. Any advice?

def add(x, y):
    return x + y


def sub(x, y):
    return x - y


def mul(x, y):
    return x * y


def div(x, y):
    value = None
    while True:
        try:
            value = x / y
            break
        except ZeroDivisionError:
            print('Value is not dividable by 0, try again')
            break
    return value


def num_input(prompt='Enter a number: '):
    while True:
        try:
            print(prompt, end='')
            x = int(input())
            break
        except ValueError:
            print('You must input a number. Try again.')
    return x


def get_two_val():
    x, y = num_input(), num_input()
    return x, y


print("Welcome to Simple Calc")

# declaration of variables
num_of_calc_counter = 0
index_of_calc = 1
calculations = []

while True:

    print("Choose from the following options:")
    print(" 1. Add")
    print(" 2. Subtract")
    print(" 3. Multiply")
    print(" 4. Divide")
    print(" 5. Sales Tax Calculator")
    print(" 6. Recent Calculations")
    print(" 0. Quit")

    usrChoice = num_input('Enter your choice: ')

    '''
    Menu workflow
        options 1-4 take in two numbers and perform the specified calculation and
        then add the result to a master list that the user can reference later.
        lastly, the workflow increments the num_of_calc variable by 1 for recent
        calc logic

        option 5 is a simple tax calculator that needs work or option to enter
        or find tax rate

        option 6 returns a list of all the calculations perform by the user
    '''
    if usrChoice is 1:
        numbers = get_two_val()
        result = add(*numbers)
        print(numbers[0], "plus", numbers[1], "equals", result)
        calculations.extend([result])
        num_of_calc_counter += 1

    elif usrChoice is 2:
        numbers = get_two_val()
        result = sub(*numbers)
        print(numbers[0], "minus", numbers[1], "equals", result)
        calculations.extend([result])
        num_of_calc_counter += 1

    elif usrChoice is 3:
        numbers = get_two_val()
        result = mul(*numbers)
        print(numbers[0], "times", numbers[1], "equals", result)
        calculations.extend([result])
        num_of_calc_counter += 1

    elif usrChoice is 4:
        numbers = get_two_val()
        result = div(*numbers)
        print(numbers[0], "divided by", numbers[1], "equals", result)
        calculations.extend([result])
        num_of_calc_counter += 1

    elif usrChoice is 5:
        tax_rate = .0875
        price = float(input("What is the price?: "))
        total_tax = tax_rate * price
        final_amount = total_tax + price
        print('Tax rate: ', tax_rate, '%')
        print('Sales tax: $', total_tax)
        print('_____________________________')
        print('Final amount: $', final_amount)
    #
    elif usrChoice is 6:
        if len(calculations) is 0:
            print('There are no calculations')
        elif num_of_calc_counter == 0:
            index_of_calc = 1
            for i in calculations:
                print(index_of_calc, i)
                index_of_calc += 1
            num_of_calc_counter += 1
        elif index_of_calc == num_of_calc_counter:
            index_of_calc = 1
            for i in calculations:
                print(index_of_calc, i)
                index_of_calc += 1
            num_of_calc_counter += 1
        elif num_of_calc_counter > index_of_calc:
            index_of_calc = 1
            for i in calculations:
                print(index_of_calc, i)
                index_of_calc += 1
            num_of_calc_counter -= 1
        elif num_of_calc_counter < index_of_calc:
            index_of_calc = 1
            for i in calculations:
                print(index_of_calc, i)
                index_of_calc += 1
            num_of_calc_counter += 1

    elif usrChoice is 0:
        break
\$\endgroup\$
  • \$\begingroup\$ Sales tax calculations are excluded from the history? Why? \$\endgroup\$ – 200_success Jan 4 at 20:02
  • 1
    \$\begingroup\$ I disagree with that close vote - this seems on-topic to me. The OP describes it as being functional. \$\endgroup\$ – Reinderien Jan 4 at 20:31
2
\$\begingroup\$

Use the operator package

This series of functions:

def add(x, y):
    return x + y


def sub(x, y):
    return x - y


def mul(x, y):
    return x * y

can go away entirely. (You can include div too if you rework the way that exceptions are handled). Instead, use the operator package.

Early return

This:

def num_input(prompt='Enter a number: '):
    while True:
        try:
            print(prompt, end='')
            x = int(input())
            break
        except ValueError:
            print('You must input a number. Try again.')
    return x

doesn't need a break. Replace the break with a return and delete the return outside of the loop.

Write a main method

...to pull your code out of global scope.

Use more loops

This:

print(" 1. Add")
print(" 2. Subtract")
print(" 3. Multiply")
print(" 4. Divide")
print(" 5. Sales Tax Calculator")
print(" 6. Recent Calculations")
print(" 0. Quit")

can be rewritten as a tuple:

menu_choices = (
    ('Add', do_add),
    ('Subtract', do_subtract),
    # ...
)

The index of the outer tuple is the user input, the first element of the inner tuple is the menu item name, and the second element of the inner tuple is the name of a function you can call to execute the menu item feature. Then your input logic can be simplified to something like

print('Choose from the following options:')
print('\n'.join('%2d. %s' % (i, name)
                for i, (name, _) in enumerate(menu_choices)))
user_choice = num_input('Enter your choice:')
if 0 <= user_choice < len(menu_choices):
    menu_choices[user_choice][1]()

Use append instead of extend

This:

calculations.extend([result])

should be

calculations.append(result)

Don't repeat yourself

These four blocks:

    elif num_of_calc_counter == 0:
        index_of_calc = 1
        for i in calculations:
            print(index_of_calc, i)
            index_of_calc += 1
        num_of_calc_counter += 1
    elif index_of_calc == num_of_calc_counter:
        index_of_calc = 1
        for i in calculations:
            print(index_of_calc, i)
            index_of_calc += 1
        num_of_calc_counter += 1
    elif num_of_calc_counter > index_of_calc:
        index_of_calc = 1
        for i in calculations:
            print(index_of_calc, i)
            index_of_calc += 1
        num_of_calc_counter -= 1
    elif num_of_calc_counter < index_of_calc:
        index_of_calc = 1
        for i in calculations:
            print(index_of_calc, i)
            index_of_calc += 1
        num_of_calc_counter += 1

do the exact same thing! So just replace them all with one else following your if len(calculations) == 0.

Also, that first if can be simplified to if not calculations.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.