Lab: The Complex Navigator
Try this code to understand how complex numbers handle coordinates:
import cmath
# 1. Define a point in 2D space
point = 4 + 3j
# 2. Calculate distance from origin (Magnitude)
distance = abs(point)
print(f"Distance: {distance}") # Result: 5.0 (3-4-5 triangle)
# 3. Rotate the point by 90 degrees
# Multiplying by 1j rotates a point by 90 degrees counter-clockwise
rotated_point = point * 1j
print(f"Original: {point} | Rotated: {rotated_point}")
# 4. Extracting Polar Coordinates
magnitude, phase = cmath.polar(point)
print(f"Angle in Radians: {phase}")Lab: The Vector Rotation Challenge (Beginner)
Scenario: You are developing a simple 2D game engine. Rotating a point 90∘ is a frequent task.
- Task: Define a complex number
z = 5 + 2j. - The Problem: Multiply
zby1jand print the result. Then multiply it by1jagain. - The Discovery: Observe how multiplying by
jrotates a point by 90∘ counter-clockwise on the complex plane. - Code Goal: “`python z = 5 + 2j rotate_90 = z * 1j rotate_180 = rotate_90 * 1j print(rotate_90, rotate_180)
Solution: The Vector Rotation Challenge
Logic: In mathematics, multiplying a coordinate (x,y) by the imaginary unit i (or j in Python) results in (−y,x), which is a 90∘ rotation.
z = 5 + 2j
# First 90-degree rotation
rotate_90 = z * 1j
print(f"90° Rotation: {rotate_90}")
# Expected Output: (-2+5j)
# Second rotation (180 degrees total)
rotate_180 = rotate_90 * 1j
print(f"180° Rotation: {rotate_180}")
# Expected Output: (-5-2j)
Lab : Safe Comparisons (Intermediate)
Scenario: You are building a monitoring tool that ranks server “health scores” represented by complex numbers (where real is uptime and imaginary is load).
- Task: Try to compare two complex numbers using
>.z1 = 3 + 4jz2 = 5 + 2j
- The Problem: Python will throw a
TypeError. - The Fix: Write a function
compare_complex(c1, c2)that compares them based on their Magnitude (distance from zero). - Hint: Use the
abs()function.
Solution: Safe Comparisons (Magnitude Ranking)
Logic: Since Python doesn’t know if 3+4j is “bigger” than 5+2j, we calculate their distance from the origin (0,0) using the Pythagorean theorem, which abs() handles automatically.
def compare_complex(c1, c2):
mag1 = abs(c1)
mag2 = abs(c2)
if mag1 > mag2:
return f"{c1} has a larger magnitude ({mag1:.2f}) than {c2} ({mag2:.2f})"
elif mag1 < mag2:
return f"{c2} has a larger magnitude ({mag2:.2f}) than {c1} ({mag1:.2f})"
else:
return "Both numbers have equal magnitude."
z1 = 3 + 4j # Magnitude 5.0
z2 = 5 + 2j # Magnitude 5.38
print(compare_complex(z1, z2))Lab: Extracting Polar Data (Advanced)
Scenario: You are working with radar data. The data arrives as (real, imag), but you need the Range (magnitude) and Bearing (angle).
- Task: Import the cmath module.
- The Problem: Use
cmath.polar()to convertz = 1 + 1jinto magnitude and phase. - The Validation: Use
cmath.rect(magnitude, phase)to convert it back to its original form. - Missing Logic to Spot: Why is the phase of
1 + 1jequal to 0.785… radians? (Hint: It is 4π or 45∘).
Solution: Extracting Polar Data
Logic: Radar and Signal systems often need “Angle and Distance” rather than “X and Y”.
import cmath
z = 1 + 1j
# Convert to Polar (Magnitude, Phase in Radians)
magnitude, phase = cmath.polar(z)
print(f"Distance: {magnitude}") # 1.414... (sqrt of 2)
print(f"Angle (Radians): {phase}") # 0.785... (pi/4)
# Convert back to Rectangular
original = cmath.rect(magnitude, phase)
print(f"Back to Rectangular: {original}")
Lab 4: Solving “Impossible” Quadratics (Architect Level)
Scenario: You are writing a mathematical solver for a DevSecOps encryption algorithm that involves square roots of negative numbers.
- Task: Solve the quadratic equation x2+1=0.
- The Problem: Using
math.sqrt(-1)will crash with aValueError. - The Solution: Use
cmath.sqrt(-1). - Architect Note: In production, always check if your inputs are likely to produce complex results to decide whether to use
math(faster) orcmath(more capable).
Solution: Solving “Impossible” Quadratics
Logic: Standard math.sqrt raises a ValueError for negative inputs because it only supports Real numbers. cmath is designed for the Complex domain.
import cmath
# Equation: x^2 + 1 = 0 -> x^2 = -1 -> x = sqrt(-1)
try:
# This would fail: import math; math.sqrt(-1)
solution1 = cmath.sqrt(-1)
solution2 = -cmath.sqrt(-1)
print(f"The roots of x^2 + 1 are: {solution1} and {solution2}")
except ValueError as e:
print(f"Calculation failed: {e}")Lab 5: Precision and Floating Point Drift (Architect Level)
Scenario: Complex numbers use two floats. This means they inherit all the “float traps” we discussed earlier.
- Task: 1. Calculate
z = (0.1 + 0.2j) + (0.1 + 0.2j). 2. Check ifz.real == 0.2andz.imag == 0.4. - The Problem: Observe the tiny precision errors in the real and imaginary components.
- The Fix: Implement a
complex_isclosefunction usingmath.isclosefor both the.realand.imagparts separately.
Solution: The “Complex Is Close” Function
Logic: To avoid floating-point drift errors in complex numbers, you must verify that both the Real and Imaginary parts are “close enough” to the target.
import math
def complex_isclose(c1, c2, rel_tol=1e-9):
real_match = math.isclose(c1.real, c2.real, rel_tol=rel_tol)
imag_match = math.isclose(c1.imag, c2.imag, rel_tol=rel_tol)
return real_match and imag_match
# Testing precision drift
z_calc = (0.1 + 0.2j) + (0.1 + 0.2j)
z_target = 0.2 + 0.4j
print(f"Direct Equality: {z_calc == z_target}") # Might be False
print(f"Secure Equality: {complex_isclose(z_calc, z_target)}") # True