diff --git a/buttons.md b/buttons.md new file mode 100644 index 0000000..43df6bb --- /dev/null +++ b/buttons.md @@ -0,0 +1,54 @@ +#list of calculator buttons and function definitions +##Core +`state` <- represents the screen + +`get current number on display` + +`clear the display` + +`add` +add(a: float, b:float) -> float + +`sub` +sub(a: float, b:float) -> float + +`multiply` + +`divide` + +`squre` + +`square_root` + +`exponentiate` + +`inverse` + +`invert_sign` + +##scientific +###Display +`switch_display_rotate` +`switch_display_str` +`display_binary` +`display_octal` +`display_decimal` +`display_hex` +###memmory +* store 1 value (for recall) + +`m+` (puts display in memory) +`mc` (clears memory) +`mrc` (puts memory on screen) + +###trig +`sin` +`cos` +`tan` +`asin` (inverse) +`acos` +`atan` +###switch trig mode +rads and degrees +rads_degrees_swap() -> str +switch and string \ No newline at end of file diff --git a/calc.py b/calc.py new file mode 100644 index 0000000..a979e76 --- /dev/null +++ b/calc.py @@ -0,0 +1,25 @@ +from calculator import State + +state = State() + +while True: + state.print() + if state.command is None: + print("current command is:", state.command) + state.user_entry = input("please enter a mathematical function or number (or type help): ") + if state.user_entry.isnumeric(): + state.user_entry = float(state.user_entry) + if state.command is None: + state.value = state.user_entry + elif state.command == "+": + state.add(state.user_entry) + elif state.command == "-": + state.sub(state.user_entry) + elif state.user_entry.upper() == "HELP": + state.help() + continue + elif state.user_entry.upper() == "EXIT": + break + else: + state.command = state.user_entry.upper() +print("thanks for pushing all my buttons") diff --git a/calculator.py b/calculator.py index 3c85ead..ab0c323 100644 --- a/calculator.py +++ b/calculator.py @@ -1,12 +1,267 @@ + +import math + class Calculator: def __init__(self): - pass - def add(self, x, y): - return x + y + self.error = False + self.result = 0 + self.degrees = True + self.display_mode = "decimal" + self.stored_number = 0 + self.exit = False + + def err(self): + self.error = True + + def eval_function(self, x: str): + """ + evaluates x to return a result + """ + try: + result = eval(x) + return result + except: + self.err() + return "Err" + + + + def add(self, a, b): + """ + ADDS TWO NUMBERS AND RETURNS RESULT + :param a: + :param b: + :return: + """ + return a + b + + + def subtract(self, x, y): + """ + SUBTRACTS TWO NUMBERS AND RETURNS RESULT + :param x: + :param y: + :return: + """ + return x - y + + + def multiply(self, x, y): + """ + MULTIPLIES TWO NUMBERS AND RETURNS RESULT + :param x: + :param y: + :return: + """ + return y * x + + + def divide(self, x, y): + + """ + DIVIDES TWO NUMBERS AND RETURNS RESULT + :param x: + :param y: + :return: + """ + try: + result = x / y + except: + result = "Err" + self.err() + return result + + return result + + + def square(self, base): + """ + SQUARES A NUMBER AND RETURNS RESULT + :param base: + :return: + """ + return base ** 2 + + + def exp(self, x, y): + """ + EXPONENTIATES TWO NUMBERS AND RETURNS RESULT + :param x: + :param y: + :return: + """ + return x ** y + + + def square_root(self, x): + """ + FINDS THE SQUARE ROOT OF A NUMBER AND RETURNS RESULT + :param x: + :return: + """ + try: + print(math.sqrt(x)) + except: + self.err() + return "Err" + return math.sqrt(x) + + + def invert(self, x): + """ + INVERSES A NUMBER AND RETURNS RESULT + :param x: + :return: + """ + try: + result = 1/x + return result + except: + self.err() + return "Err" + + + def deg_rad_swap(self): + """ + SWAPS BETWEEN RADIANS AND DEGREES + :return: + """ + self.degrees = not self.degrees + + def sin(self, x): + """ + FINDS SINE OF NUMBER AND RETURNS RESULT + :param x: + :return: + """ + try: + if self.degrees: + x = math.radians(x) + return math.sin(x) + except: + return "Err" + + def cosine(self, x): + """ + FINDS COSINE OF NUMBER AND RETURNS RESULT + :param x: + :return: + """ + try: + if self.degrees: + x = math.radians(x) + x = math.cos(x) + return x + except: + return "Err" + + def tangent(self, x): + """ + FINDS TANGENT OF NUMBER AND RETURNS RESULT + :param x: + :return: + """ + try: + if self.degrees: + x = math.radians(x) + x = math.tan(x) + return x + except: + return "Err" + + def inverse_sine(self, x): + """ + FINDS INVERSE SINE OF NUMBER AND RETURNS RESULT + :param x: + :return: + """ + try: + if self.degrees: + x = math.degrees(math.asin(x)) + else: + x = math.asin(x) + return x + except: + return "Err" + + def inverse_cosine(self, x): + """ + FINDS INVERSE COSINE OF NUMBER AND RETURNS RESULT + :param x: + :return: + """ + try: + if self.degrees: + x = math.degrees(math.acos(x)) + else: + x = math.acos(x) + return x + except: + return "Err" + + def inverse_tangent(self, x): + """ + FINDS INVERSE TANGENT OF NUMBER AND RETURNS RESULT + :param x: + :return: + """ + try: + if self.degrees: + x = math.degrees(math.atan(x)) + else: + x = math.atan(x) + return x + except: + return "Err" + + ##SECONDARY FORMULAS + + def add2(self, x): + """ + ADDS A NUMBER WITH THE SAME NUMBER + :param x: + :return: + """ + print(self.result + x) + return self.result + x + + + def subtract2(self, x): + """ + SUBTRACTS A NUMBER WITH THE SAME NUMBER + :param x: + :return: + """ + print(self.result - x) + return self.result - x + + + def multiply2(self, x): + """ + MULTIPLIES A NUMBER WITH THE SAME NUMBER + :param x: + :return: + """ + # print( self.result * x) + return self.result * x + + + def divide2(self, x): + """ + DIVIDES A NUMBER WITH THE SAME NUMBER + :param x: + :return: + """ + + print(self.result / x) + return self.result / x + + def clr(self,ce): + test = ce.upper() + if test == "CE": + self.error = False + self.result = 0 - def sub(self, x, y): - return 0 -# add lots more methods to this calculator class. diff --git a/empty_file b/empty_file new file mode 100644 index 0000000..e69de29 diff --git a/main-app.py b/main-app.py deleted file mode 100644 index a7cc4e2..0000000 --- a/main-app.py +++ /dev/null @@ -1,34 +0,0 @@ -from calculator import Calculator - - -def getTwoNumbers(): - a = float(input("first number? ")) - b = float(input("second number? ")) - return a, b - - -def displayResult(x: float): - print(x, "\n") - - -def performCalcLoop(calc): - while True: - choice = input("Operation? ") - if choice == 'q': - break # user types q to quit calulator. - elif choice == 'add': - a, b = getTwoNumbers() - displayResult(calc.add(a, b)) - else: - print("That is not a valid input.") - - -# main start -def main(): - calc = Calculator() - performCalcLoop(calc) - print("Done Calculating.") - - -if __name__ == '__main__': - main() diff --git a/main_app.py b/main_app.py new file mode 100644 index 0000000..f4cab45 --- /dev/null +++ b/main_app.py @@ -0,0 +1,371 @@ +from calculator import Calculator +import math + +calc = Calculator() + + + + + + + + +def enter_num(): + try: + num1 = float(input()) + return num1 + except: + calc.err() + + + +##Calculator Options + +def screen_options(): + if calc.degrees: + raddeg = "Degrees" + else: + raddeg = "Radians" + + print("1: Add 8: Inverse 15: M+") + print("2: Subtract 9: Sine 16: MC") + print("3: Multiply 10: Cosine 17: MRC") + print("4: Divide 11: Tangent 18: Swap Trig") + print("5: Square 12: Inverse Sine 19: Pi") + print("6: Square Root 13: Inverse Consine 20: Evaluate") + print("7: Exponent 14: Inverse Tangent 21: Exit") + print("") + print(f"Current number is: {calc.result} and trig functions are in {raddeg}") + Operation = int(input("Choose an operation: (Select the number) ")) + + memStore = None + + if Operation == 1: + print("Add") + print(f"Enter number to add to {calc.result}: ") + x = enter_num() + # print("Enter the second number: ") + # y = enter_num() + calc.result = calc.add(calc.result ,x) + return calc.result + + elif Operation == 2: + print("Subtract") + print(f"Enter number to subtract from {calc.result}: ") + x = enter_num() + # print("Enter the second number: ") + # y = enter_num() + calc.result = calc.subtract(calc.result, x) + return calc.result + + elif Operation == 3: + print("Multiply") + print(f"Enter number to multiply by {calc.result}: ") + x = enter_num() + # print("Enter the second number: ") + # y = enter_num() + calc.result = calc.multiply(calc.result, x) + return calc.result + + elif Operation == 4: + print("Divide") + print(f"Enter number to divide into {calc.result}: ") + x = enter_num() + # print("Enter the second number: ") + # y = enter_num() + # if y == 0: + # print("ERROR") + # return None + # else: + calc.result = calc.divide(calc.result, x) + return calc.result + + elif Operation == 5: + print("Square") + # print("Enter the number: ") + calc.result = calc.square(calc.result) + return calc.result + + elif Operation == 7: + print("Exponent") + print(f"Raise {calc.result} to the (enter number) power: ") + x = enter_num() + # print("Enter the exponent") + # y = enter_num() + calc.result = calc.exp(calc.result, x) + return calc.result + + elif Operation == 6: + print("Square Root") + # print("Enter the number: ") + # x = enter_num() + calc.result = calc.square_root(calc.result) + return calc.result + + elif Operation == 8: + print("Inverse") + # print("Enter the number: ") + # x = enter_num() + calc.result = calc.invert(calc.result) + return calc.result + +##TRIG FUNCTIONS + ##updated with calcments for degrees and radians + + elif Operation == 9: + print("Sine") + # if calc.degrees: + # print("Enter a number in degrees to find Sine: ") + # else: + # print("Enter a number in radians to find Sine: ") + calc.result = calc.sin(calc.result) + return calc.result + + + elif Operation == 10: + print("Cosine") + # if calc.degrees: + # print("Enter an angle in degrees to find Cosine: ") + # else: + # print("Enter an angle in radians to find Cosine: ") + # x = enter_num() + calc.result = calc.cosine(calc.result) + return calc.result + + + elif Operation == 11: + print("Tangent") + # if calc.degrees: + # print("Enter an angle in degrees to find Tangent: ") + # else: + # print("Enter an angle in radians to find Tangent: ") + # x = enter_num() + calc.result = calc.tangent(calc.result) + return calc.result + + + elif Operation == 12: + print("Inverse Sine") + # if calc.degrees: + # print("Enter a number to find the arc sine in degrees: ") + # else: + # print("Enter a number to find the arc sine in radians: ") + # x = enter_num() + result = calc.inverse_sine(calc.result) + return result + + elif Operation == 13: + print("Inverse Cosine") + # if calc.degrees: + # print("Enter an angle in degrees to find Inverse Cosine: ") + # else: + # print("Enter an angle in radians to find Inverse Cosine: ") + # x = enter_num() + calc.result = calc.inverse_cosine(calc.result) + return calc.result + + elif Operation == 14: + print("Inverse Tangent") + # if calc.degrees: + # print("Enter an angle in degrees to find Inverse Tangent: ") + # else: + # print("Enter an angle in radians to find Inverse Tangent: ") + # x = enter_num() + calc.result = calc.inverse_tangent(calc.result) + return calc.result + +##MEMORY FUNCTIONS + + elif Operation == 15: + print("M+") + calc.stored_number = float(input("Enter a number to store: ")) + print(calc.stored_number) + return calc.stored_number + + elif Operation == 16: + print("MC") + if type(calc.stored_number) != None: + print(calc.stored_number) + + elif Operation == 17: + print("MCR") + store_choice = (input("Do you want to clear memory? Y or N: ")).capitalize() + if store_choice == "Y": + calc.stored_number= 0 + else: + pass + print(calc.stored_number) + return calc.stored_number + + elif Operation == 18: + calc.deg_rad_swap() + if calc.degrees: + return ("You are in degrees mode") + else: + return ("You are in radiants mode") + + elif Operation == 19: + print("PI = ") + return 3.14159265359 + + elif Operation == 20: + print("Evaluate") + x = input("Enter what you would like evaluated: ") + calc.result = calc.eval_function(x) + return calc.result + + + + elif Operation == 21: + condi = False + print("Thank you for pushing my buttons!") + +##LOOPING OPERATIONS +###DEF FOR SECONDARY OPERATIONS + + +def choose_data_type(): + type_choice = int(input("Enter data type: 1. Decimal 2. Hexadecimal 3. Binary 4. Octal ")) + if type_choice == 1: + print(calc.result) + return (calc.result) + elif type_choice == 2: + print(hex(int(calc.result))) + return hex(int(calc.result)) + elif type_choice == 3: + print(bin(int(calc.result)).replace("0b", "")) + return bin(int(calc.result)).replace("0b", "") + elif type_choice == 4: + print(oct(int(calc.result))) + return oct(int(calc.result)) + + +def secondary_operation(): + print("1: Add 5: Square 9: M+") + print("2: Subtract 6: Square Root 10: MC") + print("3: Multiply 7: Exponent 11: MRC") + print("4: Divide 8: Inverse 12: Exit") + print("") + Operation = int(input('Choose an operation: ')) + + memStore = None + + if Operation == 1: + print("Add") + print("Enter number to add: ") + x = enter_num() + calc.result = calc.add2(x) + return calc.result + + elif Operation == 2: + print("Subtract") + print("Enter the number to subtract: ") + x = enter_num() + calc.result = calc.subtract2(x) + return calc.result + + elif Operation == 3: + print("Multiply") + print("Enter the second number: ") + x = enter_num() + calc.result = calc.multiply2(x) + return calc.result + + elif Operation == 4: + print("Divide") + print("Enter the second number: ") + x = enter_num() + calc.result = calc.divide2(x) + return calc.result + + elif Operation == 5: + print("Square") + calc.result = calc.square2(calc.result) + return calc.result + + elif Operation == 6: + print("Exponent") + print("Enter the exponent: ") + x = enter_num() + calc.result = calc.exp2(x) + return calc.result + + elif Operation == 7: + print("Square Root") + calc.result = calc.square_root2(calc.result) + return calc.result + + elif Operation == 8: + print("Inverse") + calc.result = calc.inv2(calc.result) + return calc.result + + elif Operation == 9: + memStore = calc.result + print(memStore) + return memStore + + elif Operation == 10: + if type(memStore) != None: + print(memStore) + else: + print('Empty') + + elif Operation == 11: + store_choice = (input("Do you want to clear memory? Y or N: ")).capitalize() + if store_choice == "Y": + memStore = 0 + else: + pass + print(memStore) + return memStore + + elif Operation == 12: + condi = False + print('Goodbye!') + + +###################################################################### +## on screen ## + + +#loop does not operate correctly while welcome and main are defined as functions, must keep open +def welcome(): + print("Welcome to our Calculator!") + print("How can we help you?") + print("") + + +def main(): + condi = True + while condi: + calc.result = screen_options() + print(f"Result: {calc.result}") + while calc.error: + ce = input("an error occurered'CE' (Clear Error) to continue") + calc.clr(ce) + choose_data_type() + print("") + # cont = (input("Do you continue with this number? Y or N: ")).capitalize() + # print("") + # if cont == "Y": + # condi2 = True + # while condi2: + # calc.result = secondary_operation() + # print(f"Result: {calc.result}") + # choose_data_type() + # print("") + # cont2 = (input("Do you continue with this number? Y or N: ")).capitalize() + # print("") + # if cont2 == "Y": + # condi2 = True + # else: + # break + + + +if __name__ == '__main__': + + main() + welcome() + diff --git a/new b/new new file mode 100644 index 0000000..e69de29 diff --git a/state.py b/state.py new file mode 100644 index 0000000..2cae312 --- /dev/null +++ b/state.py @@ -0,0 +1,7 @@ +class State: + def __init__(self): + error = False + result = 0 + degrees = True + display_mode = "decimal" + stored_number = 0 diff --git a/temp_script.py b/temp_script.py new file mode 100644 index 0000000..e69de29 diff --git a/test_calculator.py b/test_calculator.py new file mode 100644 index 0000000..c13a5ff --- /dev/null +++ b/test_calculator.py @@ -0,0 +1,140 @@ +import unittest +import math +from calculator import Calculator + + +class TestStringMethods(unittest.TestCase): + + def test_add(self): + c = Calculator() + self.assertEqual(c.add(3, 4), 7) + self.assertEqual(c.add(-3, -4), -7) + self.assertTrue(c.add(3, -4), -1) + + def test_eval_function(self): + c = Calculator() + self.assertEqual(c.eval_function("qw+2"), "Err") + self.assertEqual(c.eval_function("1 + 2"), 3) + + def test_subtract(self): + c = Calculator() + self.assertEqual(c.subtract(3, 4), -1) + self.assertEqual(c.subtract(-3, -4), 1) + self.assertTrue(c.subtract(3, -4), 7) + + def test_multiply(self): + c = Calculator() + self.assertEqual(c.multiply(3, 4), 12) + self.assertEqual(c.multiply(-3, -4), 12) + self.assertTrue(c.multiply(3, -4), -12) + + def test_divide(self): + c = Calculator() + self.assertEqual(c.divide(3, 4), .75) + self.assertEqual(c.divide(-3, -4), .75) + self.assertEqual(c.divide(3, -4), -.75) + self.assertEqual(c.divide(3, 0), "Err") + + def test_square(self): + c = Calculator() + self.assertEqual(c.square(3), 9) + self.assertEqual(c.square(-4), 16) + self.assertEqual(c.square(0), 0) + + def test_exp(self): + c = Calculator() + self.assertEqual(c.exp(3, 4), 81) + self.assertEqual(c.exp(3, -4), (1 / 3) * (1 / 3) * (1 / 3) * (1 / 3)) + self.assertEqual(c.exp(-3, -4), (-(1 / 3)) * (-(1 / 3)) * (-(1 / 3)) * (-(1 / 3))) + self.assertEqual(c.exp(0, 0), 1) + + def test_square_root(self): + c = Calculator() + self.assertEqual(c.square_root(-2), "Err") + self.assertEqual(c.square_root(9), 3) + self.assertEqual(c.square_root(0), 0) + + # def test_invert(self): + # c = Calculator() + # self.assertEqual(c.invert(2), 0.2) + # # self.assertEqual(c.inv(0),"Err") + + def test_add2(self): + c = Calculator() + self.assertEqual(c.add(5, 8), 13) + + def test_subtract2(self): + c = Calculator() + self.assertEqual(c.add(5, 8), 13) + + def test_multiply2(self): + c = Calculator() + self.assertEqual(c.add(5, 8), 13) + + def test_divide2(self): + c = Calculator() + self.assertEqual(c.add(5, 8), 13) + + def test_invert(self): + c = Calculator() + self.assertEqual(c.invert(5), .2) + self.assertEqual(c.invert(0), "Err") + self.assertEqual(c.invert(-5), -.2) + + def test_sin(self): + c = Calculator() + c.degrees = False + half_pi = .5 * math.pi + self.assertEqual(c.sin(half_pi),1) + self.assertEqual(c.sin("sdf"),"Err") + c.degrees = True + self.assertEqual(c.sin(90), 1) + + def test_cosine(self): + c = Calculator() + c.degrees = False + half_pi = .5 * math.pi + self.assertAlmostEqual(c.cosine(half_pi),0) + self.assertEqual(c.cosine("sdf"),"Err") + c.degrees = True + self.assertAlmostEqual(c.cosine(90), 0) + + def test_tangent(self): + c = Calculator() + c.degrees = False + quarter_pi = .25 * math.pi + self.assertAlmostEqual(c.tangent(quarter_pi),1) + self.assertEqual(c.tangent("sdf"),"Err") + c.degrees = True + self.assertAlmostEqual(c.tangent(45), 1) + + def test_invsine(self): + c = Calculator() + c.degrees = False + half_pi = .5 * math.pi + self.assertEqual(c.inverse_sine(1),half_pi) + self.assertEqual(c.inverse_sine("sdfsdf"),"Err") + c.degrees = True + self.assertEqual(c.inverse_sine(1),90) + + def test_inverse_cosine(self): + c = Calculator() + c.degrees = False + half_pi = .5 * math.pi + self.assertEqual(c.inverse_cosine(0),half_pi) + self.assertEqual(c.inverse_cosine("sdfsdf"),"Err") + c.degrees = True + self.assertEqual(c.inverse_cosine(0),90) + + def test_inverse_tangent(self): + c = Calculator() + c.degrees = False + quarter_pi = .25 * math.pi + self.assertEqual(c.inverse_tangent(1),quarter_pi) + self.assertEqual(c.inverse_tangent("sdfsdf"),"Err") + c.degrees = True + self.assertEqual(c.inverse_tangent(1),45) + + +if __name__ == '__main__': + unittest.main() diff --git a/calctests.py b/test_main-app.py similarity index 87% rename from calctests.py rename to test_main-app.py index 1964570..cd7ee5e 100644 --- a/calctests.py +++ b/test_main-app.py @@ -2,7 +2,7 @@ from calculator import Calculator -class TestStringMethods(unittest.TestCase): +class TestCalculatorMethods(unittest.TestCase): def test_add(self): c = Calculator() @@ -22,4 +22,4 @@ def test_sub(self): if __name__ == '__main__': - unittest.main() + unittest.main() \ No newline at end of file