Exploring Python: How to Define a Class for Complex Number Objects

πŸ’‘ Problem Formulation: Complex numbers, used extensively in engineering and science, consist of a real part and an imaginary part. For example, 3 + 4i is a complex number with the real part being 3 and the imaginary part 4i. This article explores how to create a Python class that can handle complex numbers, allowing operations such as addition, subtraction, multiplication, and division, similar to built-in numeric types.

Method 1: Defining Basic Structure

This method involves creating a ComplexNumber class with a constructor that initializes the real and imaginary parts. It includes basic methods for string representation and accessing the real and imaginary parts.

Here’s an example:

class ComplexNumber:
    def __init__(self, real, imaginary):
        self.real = real
        self.imaginary = imaginary
        
    def __repr__(self):
        return f"{self.real} + {self.imaginary}i"
    
# Creating a complex number object
complex_num = ComplexNumber(3, 4)
print(complex_num)

Output:

3 + 4i

This class defines __init__ to set up the real and imaginary attributes and __repr__ to provide a string representation. When a ComplexNumber object is printed, the output displays the formatted complex number.

Method 2: Implementing Arithmetic Operations

Building on the basic structure, this method adds functionality to perform arithmetic operations such as addition and subtraction by overriding the __add__ and __sub__ magic methods.

Here’s an example:

class ComplexNumber:
    # ... (previous code) ...
    
    def __add__(self, other):
        return ComplexNumber(self.real + other.real, self.imaginary + other.imaginary)
    
    def __sub__(self, other):
        return ComplexNumber(self.real - other.real, self.imaginary - other.imaginary)

# Performing addition and subtraction
complex_num1 = ComplexNumber(3, 4)
complex_num2 = ComplexNumber(1, 2)
print(complex_num1 + complex_num2)
print(complex_num1 - complex_num2)

Output:

4 + 6i
2 + 2i

The __add__ and __sub__ methods enable adding or subtracting two ComplexNumber objects, resulting in a new ComplexNumber instance with the combined values.

Method 3: Overriding the Multiplication Operator

This method introduces the ability to multiply two complex numbers by implementing the __mul__ method, which defines the algorithm for complex multiplication.

Here’s an example:

class ComplexNumber:
    # ... (previous code) ...
    
    def __mul__(self, other):
        real = (self.real * other.real) - (self.imaginary * other.imaginary)
        imaginary = (self.real * other.imaginary) + (self.imaginary * other.real)
        return ComplexNumber(real, imaginary)

# Multiplying two complex numbers
complex_num1 = ComplexNumber(3, 4)
complex_num2 = ComplexNumber(1, 2)
print(complex_num1 * complex_num2)

Output:

-5 + 10i

The __mul__ method applies the formula (a+bi)(c+di) = (ac-bd) + (ad+bc)i to perform complex multiplication. The resulting ComplexNumber object correctly represents the product of the two operands.

Method 4: Including Division Operation

This technique introduces division into the ComplexNumber class. It overrides the __truediv__ method to define division of complex numbers in accordance with the mathematical rules.

Here’s an example:

class ComplexNumber:
    # ... (previous code) ...
    
    def __truediv__(self, other):
        denominator = other.real**2 + other.imaginary**2
        real = (self.real * other.real + self.imaginary * other.imaginary) / denominator
        imaginary = (self.imaginary * other.real - self.real * other.imaginary) / denominator
        return ComplexNumber(real, imaginary)

# Dividing two complex numbers
complex_num1 = ComplexNumber(3, 4)
complex_num2 = ComplexNumber(1, 2)
print(complex_num1 / complex_num2)

Output:

2.2 + 0.4i

The __truediv__ method implements complex number division using the formula ((ac+bd)/(c^2+d^2)) + ((bc-ad)/(c^2+d^2))i. By doing so, it returns the quotient as a new ComplexNumber object.

Bonus One-Liner Method 5: Using Data Classes

For a more concise definition of a complex number class in Python 3.7+, we can leverage the dataclass decorator for automatic generation of special methods like __init__ and __repr__.

Here’s an example:

from dataclasses import dataclass

@dataclass
class ComplexNumber:
    real: float
    imaginary: float

# Instantiating a complex number with data classes
complex_num = ComplexNumber(3, 4)
print(complex_num)

Output:

ComplexNumber(real=3, imaginary=4)

With the dataclass decorator, the class instantiation and representation methods are automatically created, saving the need to explicitly define them.

Summary/Discussion

  • Method 1: Basic Structure. Strengths: Establishes the groundwork for the class. Weaknesses: Lacks advanced operations.
  • Method 2: Arithmetic Operations. Strengths: Enables basic mathematical interactions. Weaknesses: Only includes addition and subtraction.
  • Method 3: Multiplication Operator. Strengths: Adds complexity with multiplication. Weaknesses: Can become complicated with non-standard operations.
  • Method 4: Division Operation. Strengths: Completes the set of elementary complex operations. Weaknesses: Implementation requires thorough understanding of complex arithmetic.
  • Method 5: Using Data Classes. Strengths: Provides a quick and clean setup. Weaknesses: Limited customization and control over the class internal behavior.