HiveBrain v1.2.0
Get Started
← Back to all entries
patternpythonMinor

Calculator Program which can operate on multiple numbers

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
cannumbersoperateprogrammultiplewhichcalculator

Problem

All the calculator programs I have seen so far seem long, complicated and they can only operate on two numbers. I am trying to write one that is simple, short, and it can operate on as many numbers as you want. After implementing suggestions from my previous question regarding use of operator.XXX and functools.reduce I've got a new version for review:

import operator
import functools
amount_of_numbers = int(input("How many numbers?"))
my_operator = input("Which operator (*, /, +, -)?")
if my_operator == "/":
    numbers=[float(input("Number: ")) for _ in range(amount_of_numbers)]
else:
    numbers = [int(input("Number: ")) for _ in range(amount_of_numbers)]

OPERATORS = {
    '+': operator.add,
    '-': operator.sub,
    '*': operator.mul,
    '/': operator.floordiv
}

INIT_VALUE = {
    '-': 0,
    '/': 1.00,
    '+': 0,
    '*': 1
}
result = functools.reduce(OPERATORS[my_operator], numbers, INIT_VALUE[my_operator])
print (result)

Solution

After a little back and forth, we got the suggestions of the previous question implemented. However there are still some minor issues:

-
Kind of strange mixing int and float calculations – I know you got 0 when doing divisions, but that is more of a test number issue than a fault in code. As it currently stands you do float numbers for the division, but your operator is operator.floordiv which rounds of the division.

If you want to use floats when dividing, then change to operator.div, and if you want to use integer division remove the float(input("Number: ")) ..., and let the operator.floordiv remain.

-
No need for the initializing values when using functools.reduce – The newer reduce function does what is expected when reducing, so you don't need this at all in the new code.

-
The advice to use doctest still applies – This both provides examples for use, and verifies that your code does what it is expected to do.

  • Don't use top level code, include it in main() - Move all of your code at the top level into a function, which you call from if __name__ == '__main__':, as this cleans up the code interface, allows your function to be called if imported in another file, and it looks nice.



Refactored code

When implementing all of this, and using integer division the code looks like this:

import operator
import functools
import doctest

OPERATION = {
    '+': operator.add,
    '-': operator.sub,
    '*': operator.mul,
    '/': operator.floordiv
}

def calculate(numbers=None, operator=None):
    """Apply the operator to all numbers, and print result.

    >>> calculate([1, 2, 3, 4], '+')
    10
    >>> calculate([1, 2, 3, 4], '-')
    -8
    >>> calculate([1, 2, 3, 4], '*')
    24
    >>> calculate([120, 2, 3, 4], '/')
    5
    """

    if not numbers:
        amount_of_numbers = int(input("How many numbers? "))
        numbers = [int(input("Number: ")) for _ in range(amount_of_numbers)]

    if not operator:        
        operator = input("Which operator (*, /, +, -)? ")

    result = functools.reduce(OPERATION[operator], numbers)
    print(result)

if __name__ == '__main__':
    doctest.testmod()
    calculate()


Note how this way of making it a function allows for 'proper' use as a function, whilst still allowing for user to input the missing numbers and/or operator of choice.

Another possible extension would be to add another parameter to control whether it is printing the result, or returning it for further calculations. Possibly even adding a loop around it, so you can repeat calculating other stuff?

Code Snippets

import operator
import functools
import doctest


OPERATION = {
    '+': operator.add,
    '-': operator.sub,
    '*': operator.mul,
    '/': operator.floordiv
}

def calculate(numbers=None, operator=None):
    """Apply the operator to all numbers, and print result.

    >>> calculate([1, 2, 3, 4], '+')
    10
    >>> calculate([1, 2, 3, 4], '-')
    -8
    >>> calculate([1, 2, 3, 4], '*')
    24
    >>> calculate([120, 2, 3, 4], '/')
    5
    """

    if not numbers:
        amount_of_numbers = int(input("How many numbers? "))
        numbers = [int(input("Number: ")) for _ in range(amount_of_numbers)]

    if not operator:        
        operator = input("Which operator (*, /, +, -)? ")

    result = functools.reduce(OPERATION[operator], numbers)
    print(result)

if __name__ == '__main__':
    doctest.testmod()
    calculate()

Context

StackExchange Code Review Q#113427, answer score: 3

Revisions (0)

No revisions yet.