Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added __pycache__/calculator.cpython-313.pyc
Binary file not shown.
Binary file added __pycache__/complex.cpython-313.pyc
Binary file not shown.
115 changes: 115 additions & 0 deletions complex.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
# complex.py
from calculator import Calculator
import re
import cmath

def _format_complex(c):
"""
Helper function to format a Python complex object back into a
clean 'a+bj' string without parentheses to match lab requirements.
"""
res = str(c).replace(' ', '')
if res.startswith('(') and res.endswith(')'):
res = res[1:-1]
return res

def parse_complex_string(expression):
"""
Parses an input string like '(3+2j) * (5+3j)'.
Extracts the two complex numbers and the mathematical operator.
"""
# Regex to capture everything inside the parentheses and the operator between them
pattern = r'\s*\(([^)]+)\)\s*([+\-*/])\s*\(([^)]+)\)\s*'
match = re.match(pattern, expression)

if not match:
raise ValueError("Invalid complex expression format. Expected: '(a+bj) op (c+dj)'")

c1_str, operator, c2_str = match.groups()

# Remove any internal spaces (e.g., '3 + 2j' becomes '3+2j')
return c1_str.replace(' ', ''), operator, c2_str.replace(' ', '')

def add_complex(c1, c2):
"""
Member 2: Handles the addition of two complex numbers[cite: 120].
"""
pass

def subtract_complex(c1, c2):
"""
Member 2: Handles the subtraction of c2 from c1[cite: 120].
"""
pass

def multiply_complex(c1, c2):
"""
Member 3: Handles the multiplication of two complex numbers[cite: 120].
"""

calc = Calculator()

# 1. Convert the incoming strings to Python complex objects
c1 = complex(c1_str)
c2 = complex(c2_str)

a, b = c1.real, c1.imag
c, d = c2.real, c2.imag

# (a+bi)*(c+di) = (ac - bd) + (ad + bc)i
real_part = calc.subtract(calc.multiply(a, c), calc.multiply(b, d))
imag_part = calc.add(calc.multiply(a, d), calc.multiply(b, c))

# 4. Reconstruct into a complex object and format back to a string
result = complex(real_part, imag_part)
return _format_complex(result)

def divide_complex(c1, c2):
"""
Member 3: Handles the division of c1 by c2[cite: 120].
Must include error handling for division by zero.
"""
# c1 and c2 are tuples: (real, imag)
calc = Calculator()

# 1. Convert the incoming strings to Python complex objects
c1 = complex(c1_str)
c2 = complex(c2_str)

a, b = c1.real, c1.imag
c, d = c2.real, c2.imag

# denominator = c^2 + d^2
denominator = calc.add(calc.multiply(c, c), calc.multiply(d, d))
if denominator == 0:
raise ValueError("Division by zero in complex division")
# real part: (ac + bd) / (c^2 + d^2)
real_num = calc.add(calc.multiply(a, c), calc.multiply(b, d))
real_part = calc.divide(real_num, denominator)
# imag part: (bc - ad) / (c^2 + d^2)
imag_num = calc.subtract(calc.multiply(b, c), calc.multiply(a, d))
imag_part = calc.divide(imag_num, denominator)

result = complex(real_part, imag_part)
return _format_complex(result)

def compute_magnitude(c):
"""
Member 4: Calculates the magnitude of a single complex number[cite: 122].
"""
pass

def compute_phase(c):
"""
Member 4: Calculates the phase (angle) of a single complex number[cite: 122].
"""
pass

def evaluate_complex_expression(expression):
"""
Member 5 (Integrator): The main runner function.
Takes the raw string, passes it to parse_complex_string,
routes the parsed data to the correct math function above,
and returns the final string result.
"""

100 changes: 100 additions & 0 deletions test_complex.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
# test_complex.py
import unittest
from complex import (
parse_complex_string, add_complex, subtract_complex,
multiply_complex, divide_complex, compute_magnitude,
compute_phase, evaluate_complex_expression
)

class TestComplexArithmetic(unittest.TestCase):

# --- Parser Tests ---
def test_parse_complex_string_valid(self):
c1, op, c2 = parse_complex_string('(3 + 2j) * (5+ 3j)')
self.assertEqual(c1, '3+2j')
self.assertEqual(op, '*')
self.assertEqual(c2, '5+3j')

def test_parse_complex_string_invalid(self):
# Boundary Condition: Missing brackets should raise a ValueError
with self.assertRaises(ValueError):
parse_complex_string('3+2j * 5+3j')

# --- Member 2 Tests ---
def test_add_complex(self):
# Test normal addition and negative addition
pass

def test_subtract_complex(self):
# Test normal subtraction
pass

# --- Member 3 Tests ---

def test_multiply_complex(self):
# Normal cases
self.assertEqual(multiply_complex((3, 2), (5, 3)), (9, 19)) # (3+2j)*(5+3j) = (3*5-2*3, 3*3+2*5) = (15-6, 9+10) = (9, 19)
self.assertEqual(multiply_complex((0, 0), (5, 3)), (0, 0)) # Zero times anything
self.assertEqual(multiply_complex((1, 0), (0, 1)), (0, 1)) # (1+0j)*(0+1j) = (0, 1)
self.assertEqual(multiply_complex((2, -3), (-1, 4)), (10, 11)) # (2-3j)*(-1+4j) = (2*-1-(-3)*4, 2*4+(-3)*-1) = (-2+12, 8+3) = (10, 11)

# Boundary cases
self.assertEqual(multiply_complex((0, 0), (0, 0)), (0, 0)) # Both zero
self.assertEqual(multiply_complex((999999, 0), (0, 999999)), (0, 999999*999999))
self.assertEqual(multiply_complex((-1, -1), (-1, -1)), (0, 2))

# Invalid input handling
with self.assertRaises(TypeError):
multiply_complex((1,), (2, 3)) # Too few elements
with self.assertRaises(TypeError):
multiply_complex((1, 2, 3), (2, 3)) # Too many elements
with self.assertRaises(TypeError):
multiply_complex((1, 'a'), (2, 3)) # Non-numeric
with self.assertRaises(TypeError):
multiply_complex('not a tuple', (2, 3))


def test_divide_complex(self):
# Normal cases
self.assertEqual(divide_complex((3, 2), (5, 3)), (0.6341463414634146, 0.04878048780487805))
self.assertEqual(divide_complex((0, 0), (5, 3)), (0.0, 0.0))
self.assertEqual(divide_complex((1, 0), (1, 0)), (1.0, 0.0))
self.assertEqual(divide_complex((2, -3), (-1, 4)), (-0.6470588235294118, -0.5294117647058824))

# Boundary cases
self.assertEqual(divide_complex((0, 0), (0, 1)), (0.0, 0.0))
self.assertEqual(divide_complex((999999, 0), (0, 999999)), (0.0, -1.0))
self.assertEqual(divide_complex((-1, -1), (-1, -1)), (1.0, 0.0))

# Invalid input handling
with self.assertRaises(TypeError):
divide_complex((1,), (2, 3)) # Too few elements
with self.assertRaises(TypeError):
divide_complex((1, 2, 3), (2, 3)) # Too many elements
with self.assertRaises(TypeError):
divide_complex((1, 'a'), (2, 3)) # Non-numeric
with self.assertRaises(TypeError):
divide_complex('not a tuple', (2, 3))


def test_divide_complex_by_zero(self):
# Test division by zero exception handling
with self.assertRaises(ValueError):
divide_complex((1, 2), (0, 0))

# --- Member 4 Tests ---
def test_compute_magnitude(self):
# Test magnitude calculations
pass

def test_compute_phase(self):
# Test phase calculations (check against known angles)
pass

# --- Member 5 Tests (Integration) ---
def test_evaluate_complex_expression(self):
# Test the full pipeline from raw string to final output
pass

if __name__ == "__main__":
unittest.main()