Skip to main content

math - Mathematical Functions

The math module provides access to mathematical functions and constants defined by the C standard. This module is essential for coding interviews involving mathematical computations, algorithms, and numerical analysis.

Official Documentation: Python math Module
Tutorial Reference: Numeric Types

📚 Basic Usage

Simple Example

import math

# Basic mathematical operations
print(math.sqrt(16)) # 4.0 - Square root
print(math.pow(2, 3)) # 8.0 - Power function
print(math.ceil(4.3)) # 5 - Ceiling function
print(math.floor(4.7)) # 4 - Floor function

# Mathematical constants
print(math.pi) # 3.141592653589793
print(math.e) # 2.718281828459045

# Logarithms
print(math.log(10)) # 2.302585092994046 - Natural log
print(math.log10(100)) # 2.0 - Base-10 logarithm
print(math.log2(8)) # 3.0 - Base-2 logarithm

Core Functions

import math

# Trigonometric functions (angles in radians)
angle = math.pi / 4 # 45 degrees
print(math.sin(angle)) # 0.7071067811865476
print(math.cos(angle)) # 0.7071067811865476
print(math.tan(angle)) # 1.0

# Convert degrees to radians and vice versa
degrees = 90
radians = math.radians(degrees) # 1.5707963267948966
back_to_degrees = math.degrees(radians) # 90.0

# Hyperbolic functions
print(math.sinh(1)) # 1.1752011936438014
print(math.cosh(1)) # 1.5430806348152437
print(math.tanh(1)) # 0.7615941559557649

Common Patterns

import math

# Pattern 1: Rounding operations
x = 4.7
print(math.ceil(x)) # 5 - Always round up
print(math.floor(x)) # 4 - Always round down
print(math.trunc(x)) # 4 - Truncate decimal part

# Pattern 2: Power and root operations
base, exponent = 2, 3
print(math.pow(base, exponent)) # 8.0 - Power function
print(math.sqrt(16)) # 4.0 - Square root
print(math.cbrt(27)) # 3.0 - Cube root (Python 3.11+)

# Pattern 3: Logarithmic calculations
value = 1000
print(math.log(value)) # Natural logarithm
print(math.log10(value)) # Base-10 logarithm
print(math.log2(value)) # Base-2 logarithm
print(math.log(value, 5)) # Custom base logarithm

🔧 Math Module API Reference

Number-Theoretic and Representation Functions

FunctionDescriptionReturn TypeExample
math.ceil(x)Smallest integer ≥ xintceil(4.3) → 5
math.comb(n, k)Binomial coefficient C(n,k)intcomb(5, 2) → 10
math.copysign(mag, sign)Magnitude of mag with sign of signfloatcopysign(3, -1) → -3.0
math.fabs(x)Absolute value as floatfloatfabs(-5.5) → 5.5
math.factorial(n)n! factorialintfactorial(5) → 120
math.floor(x)Largest integer ≤ xintfloor(4.7) → 4
math.fmod(x, y)x mod y as floatfloatfmod(7.5, 2.5) → 2.5
math.frexp(x)Mantissa and exponent of xtuplefrexp(8) → (0.5, 4)
math.fsum(iterable)Accurate floating-point sumfloatfsum([0.1, 0.1, 0.1]) → 0.3
math.gcd(a, b)Greatest common divisorintgcd(48, 18) → 6
math.isclose(a, b)Test if values are closeboolisclose(0.1+0.2, 0.3) → True
math.isfinite(x)Check if x is finiteboolisfinite(1.0) → True
math.isinf(x)Check if x is infiniteboolisinf(float('inf')) → True
math.isnan(x)Check if x is NaNboolisnan(float('nan')) → True
math.isqrt(n)Integer square rootintisqrt(10) → 3
math.lcm(*args)Least common multipleintlcm(12, 18) → 36
math.ldexp(x, i)x * (2**i)floatldexp(0.5, 4) → 8.0
math.modf(x)Fractional and integer partstuplemodf(4.7) → (0.7, 4.0)
math.nextafter(x, y)Next float after x toward yfloatnextafter(1.0, 2.0)
math.perm(n, k)Permutations P(n,k)intperm(5, 2) → 20
math.prod(iterable)Product of all elementsnumberprod([2, 3, 4]) → 24
math.remainder(x, y)IEEE remainderfloatremainder(7, 3) → 1.0
math.trunc(x)Truncate to integerinttrunc(4.7) → 4
math.ulp(x)Unit in last placefloatulp(1.0) → 2.22e-16

Power and Logarithmic Functions

FunctionDescriptionReturn TypeExample
math.exp(x)e^xfloatexp(1) → 2.718281828459045
math.exp2(x)2^xfloatexp2(3) → 8.0
math.expm1(x)e^x - 1floatexpm1(1) → 1.718281828459045
math.log(x[, base])Logarithm of x to basefloatlog(8, 2) → 3.0
math.log1p(x)log(1+x)floatlog1p(1) → 0.6931471805599453
math.log2(x)Base-2 logarithmfloatlog2(8) → 3.0
math.log10(x)Base-10 logarithmfloatlog10(100) → 2.0
math.pow(x, y)x^yfloatpow(2, 3) → 8.0
math.sqrt(x)Square rootfloatsqrt(16) → 4.0
math.cbrt(x)Cube root (Python 3.11+)floatcbrt(27) → 3.0

Trigonometric Functions

FunctionDescriptionReturn TypeExample
math.acos(x)Arc cosine in radiansfloatacos(0.5) → 1.047197551
math.asin(x)Arc sine in radiansfloatasin(0.5) → 0.523598776
math.atan(x)Arc tangent in radiansfloatatan(1) → 0.785398163
math.atan2(y, x)Arc tangent of y/xfloatatan2(1, 1) → 0.785398163
math.cos(x)Cosine of x (radians)floatcos(0) → 1.0
math.dist(p, q)Euclidean distancefloatdist([0,0], [3,4]) → 5.0
math.hypot(*args)Euclidean normfloathypot(3, 4) → 5.0
math.sin(x)Sine of x (radians)floatsin(pi/2) → 1.0
math.tan(x)Tangent of x (radians)floattan(pi/4) → 1.0

Hyperbolic Functions

FunctionDescriptionReturn TypeExample
math.acosh(x)Inverse hyperbolic cosinefloatacosh(2) → 1.316957897
math.asinh(x)Inverse hyperbolic sinefloatasinh(1) → 0.881373587
math.atanh(x)Inverse hyperbolic tangentfloatatanh(0.5) → 0.549306144
math.cosh(x)Hyperbolic cosinefloatcosh(0) → 1.0
math.sinh(x)Hyperbolic sinefloatsinh(0) → 0.0
math.tanh(x)Hyperbolic tangentfloattanh(0) → 0.0

Angular Conversion

FunctionDescriptionReturn TypeExample
math.degrees(x)Convert radians to degreesfloatdegrees(pi) → 180.0
math.radians(x)Convert degrees to radiansfloatradians(180) → 3.141592654

Special Functions

FunctionDescriptionReturn TypeExample
math.erf(x)Error functionfloaterf(1) → 0.842700793
math.erfc(x)Complementary error functionfloaterfc(1) → 0.157299207
math.gamma(x)Gamma functionfloatgamma(5) → 24.0
math.lgamma(x)Log gamma functionfloatlgamma(5) → 3.178053830

Mathematical Constants

ConstantDescriptionValueExample Use
math.piπ (pi)3.141592653589793Circle calculations
math.ee (Euler's number)2.718281828459045Exponential functions
math.tau2π (tau)6.283185307179586Full circle radians
math.infPositive infinityinfComparisons
math.nanNot a NumbernanInvalid operations

🐛 Common Errors and Troubleshooting

Typical Error Messages

import math

# Error 1: ValueError - Domain errors
try:
math.sqrt(-1) # ValueError: math domain error
except ValueError as e:
print(f"Domain error: {e}")

try:
math.log(0) # ValueError: math domain error
except ValueError as e:
print(f"Log domain error: {e}")

# Error 2: OverflowError - Result too large
try:
math.exp(1000) # OverflowError: math range error
except OverflowError as e:
print(f"Overflow error: {e}")

# Error 3: TypeError - Wrong argument type
try:
math.sqrt("16") # TypeError: must be real number, not str
except TypeError as e:
print(f"Type error: {e}")

Debugging Tips

import math

# Check for special values before operations
def safe_sqrt(x):
if math.isnan(x):
return float('nan')
if x < 0:
raise ValueError(f"Cannot take square root of negative number: {x}")
return math.sqrt(x)

# Handle floating-point precision issues
def compare_floats(a, b, tolerance=1e-9):
return math.isclose(a, b, rel_tol=tolerance)

# Check for infinity and NaN
def validate_number(x):
if math.isinf(x):
print(f"Warning: {x} is infinite")
elif math.isnan(x):
print(f"Warning: {x} is NaN")
elif not math.isfinite(x):
print(f"Warning: {x} is not finite")
return math.isfinite(x)

# Example usage
print(safe_sqrt(16)) # 4.0
print(compare_floats(0.1 + 0.2, 0.3)) # True
print(validate_number(math.inf)) # Warning: inf is infinite, False

Error Handling Patterns

import math

def robust_mathematical_operation(x, y):
"""Demonstrates robust error handling for math operations."""
try:
# Validate inputs
if not isinstance(x, (int, float)) or not isinstance(y, (int, float)):
raise TypeError("Arguments must be numeric")

if math.isnan(x) or math.isnan(y):
return float('nan')

if math.isinf(x) or math.isinf(y):
return float('inf')

# Perform operation with domain checking
if x <= 0:
raise ValueError("x must be positive for logarithm")

result = math.log(x) / math.log(y) if y > 0 and y != 1 else None

if result is None:
raise ValueError("Invalid base for logarithm")

return result

except (ValueError, TypeError, OverflowError) as e:
print(f"Mathematical operation failed: {e}")
return None

# Example usage
print(robust_mathematical_operation(8, 2)) # 3.0
print(robust_mathematical_operation(-1, 2)) # None (with error message)
print(robust_mathematical_operation("8", 2)) # None (with error message)

🎯 Primary Use Cases

1. Algorithm Implementation - Distance Calculations

Use Case: Calculate distances in computational geometry and pathfinding algorithms
Why math: Provides optimized implementations of square root and power functions
Code Example:

import math

def euclidean_distance(point1, point2):
"""Calculate Euclidean distance between two points."""
return math.sqrt(sum((a - b) ** 2 for a, b in zip(point1, point2)))

def manhattan_distance(point1, point2):
"""Calculate Manhattan distance between two points."""
return sum(abs(a - b) for a, b in zip(point1, point2))

def distance_using_hypot(point1, point2):
"""Calculate distance using math.hypot for better precision."""
return math.hypot(*(a - b for a, b in zip(point1, point2)))

# Example usage
p1, p2 = (0, 0), (3, 4)
print(f"Euclidean: {euclidean_distance(p1, p2)}") # 5.0
print(f"Manhattan: {manhattan_distance(p1, p2)}") # 7
print(f"Hypot: {distance_using_hypot(p1, p2)}") # 5.0

# For 3D points
p3d_1, p3d_2 = (1, 2, 3), (4, 6, 8)
print(f"3D Distance: {distance_using_hypot(p3d_1, p3d_2)}") # 7.071067812

2. Number Theory Problems - GCD and Mathematical Computations

Use Case: Solve problems involving greatest common divisors, factorials, and combinatorics
Why math: Optimized implementations of number theory functions
Code Example:

import math

def extended_gcd(a, b):
"""Extended Euclidean Algorithm using math.gcd."""
def extended_gcd_recursive(a, b):
if a == 0:
return b, 0, 1
gcd, x1, y1 = extended_gcd_recursive(b % a, a)
x = y1 - (b // a) * x1
y = x1
return gcd, x, y

return extended_gcd_recursive(a, b)

def solve_congruence(a, b, m):
"""Solve ax ≡ b (mod m) using GCD."""
gcd = math.gcd(a, m)
if b % gcd != 0:
return None # No solution

# Reduce the problem
a, b, m = a // gcd, b // gcd, m // gcd
gcd, x, y = extended_gcd(a, m)

return (x * b) % m

def combinations_and_permutations(n, r):
"""Calculate combinations and permutations efficiently."""
if r > n or r < 0:
return 0, 0

# Using math functions (Python 3.8+)
combinations = math.comb(n, r)
permutations = math.perm(n, r)

# Alternative using factorial
combinations_alt = math.factorial(n) // (math.factorial(r) * math.factorial(n - r))
permutations_alt = math.factorial(n) // math.factorial(n - r)

return combinations, permutations

# Example usage
print(f"GCD(48, 18): {math.gcd(48, 18)}") # 6
print(f"LCM(12, 18): {math.lcm(12, 18)}") # 36

gcd, x, y = extended_gcd(48, 18)
print(f"Extended GCD: {gcd}, coefficients: {x}, {y}") # 6, -1, 3

solution = solve_congruence(3, 1, 7)
print(f"Solution to 3x ≡ 1 (mod 7): x ≡ {solution} (mod 7)") # 5

comb, perm = combinations_and_permutations(5, 2)
print(f"C(5,2) = {comb}, P(5,2) = {perm}") # 10, 20

3. Floating-Point Precision and Comparison

Use Case: Handle floating-point arithmetic precision issues in algorithms
Why math: Provides robust comparison and precision handling functions
Code Example:

import math

def precise_sum(numbers):
"""Calculate sum with high precision using math.fsum."""
# Regular sum vs math.fsum
regular_sum = sum(numbers)
precise_sum = math.fsum(numbers)

return regular_sum, precise_sum

def safe_division_with_remainder(dividend, divisor):
"""Perform division with proper remainder handling."""
if divisor == 0:
return None, None

# IEEE 754 remainder (preferred for algorithms)
ieee_remainder = math.remainder(dividend, divisor)

# Traditional modulo
traditional_mod = dividend % divisor

# Float modulo
float_mod = math.fmod(dividend, divisor)

return {
'quotient': dividend // divisor,
'ieee_remainder': ieee_remainder,
'traditional_mod': traditional_mod,
'float_mod': float_mod
}

def compare_algorithms_results(result1, result2, tolerance=1e-9):
"""Compare results from different algorithms with tolerance."""
if math.isnan(result1) or math.isnan(result2):
return math.isnan(result1) and math.isnan(result2)

if math.isinf(result1) or math.isinf(result2):
return result1 == result2 # Both must be same infinity

return math.isclose(result1, result2, rel_tol=tolerance, abs_tol=tolerance)

# Example usage - floating point precision
numbers = [0.1] * 10
regular, precise = precise_sum(numbers)
print(f"Regular sum: {regular}") # 0.9999999999999999
print(f"Precise sum: {precise}") # 1.0
print(f"Are equal: {math.isclose(regular, 1.0)}") # True

# Division and remainders
result = safe_division_with_remainder(7.5, 2.5)
if result:
print(f"Division results: {result}")
# {'quotient': 3.0, 'ieee_remainder': 0.0, 'traditional_mod': 0.0, 'float_mod': 0.0}

# Algorithm comparison
algorithm1_result = math.sqrt(2) ** 2
algorithm2_result = 2.0
print(f"Results are equivalent: {compare_algorithms_results(algorithm1_result, algorithm2_result)}") # True

4. Trigonometry and Geometry in Algorithms

Use Case: Implement geometric algorithms involving angles, rotations, and coordinate transformations
Why math: Comprehensive trigonometric functions with proper angle handling
Code Example:

import math

def rotate_point(point, angle_degrees, center=(0, 0)):
"""Rotate a point around a center by given angle."""
x, y = point
cx, cy = center

# Convert to radians and translate to origin
angle_rad = math.radians(angle_degrees)
x_translated = x - cx
y_translated = y - cy

# Apply rotation matrix
cos_angle = math.cos(angle_rad)
sin_angle = math.sin(angle_rad)

x_rotated = x_translated * cos_angle - y_translated * sin_angle
y_rotated = x_translated * sin_angle + y_translated * cos_angle

# Translate back
return (x_rotated + cx, y_rotated + cy)

def calculate_polygon_area(vertices):
"""Calculate area of polygon using shoelace formula."""
n = len(vertices)
if n < 3:
return 0

area = 0
for i in range(n):
j = (i + 1) % n
area += vertices[i][0] * vertices[j][1]
area -= vertices[j][0] * vertices[i][1]

return abs(area) / 2

def angle_between_vectors(v1, v2):
"""Calculate angle between two vectors."""
# Calculate dot product and magnitudes
dot_product = sum(a * b for a, b in zip(v1, v2))
magnitude1 = math.sqrt(sum(a ** 2 for a in v1))
magnitude2 = math.sqrt(sum(a ** 2 for a in v2))

if magnitude1 == 0 or magnitude2 == 0:
return 0

# Calculate angle using arccos
cos_angle = dot_product / (magnitude1 * magnitude2)

# Clamp to [-1, 1] to handle floating-point errors
cos_angle = max(-1, min(1, cos_angle))

angle_rad = math.acos(cos_angle)
return math.degrees(angle_rad)

# Example usage
# Rotate a point 90 degrees around origin
original_point = (1, 0)
rotated_point = rotate_point(original_point, 90)
print(f"Point {original_point} rotated 90°: {rotated_point}") # (0.0, 1.0)

# Calculate area of a triangle
triangle = [(0, 0), (4, 0), (2, 3)]
area = calculate_polygon_area(triangle)
print(f"Triangle area: {area}") # 6.0

# Angle between vectors
v1, v2 = (1, 0), (0, 1)
angle = angle_between_vectors(v1, v2)
print(f"Angle between {v1} and {v2}: {angle}°") # 90.0

# Complex geometric calculation
def distance_point_to_line(point, line_start, line_end):
"""Calculate shortest distance from point to line segment."""
px, py = point
x1, y1 = line_start
x2, y2 = line_end

# Line length squared
line_length_sq = (x2 - x1) ** 2 + (y2 - y1) ** 2

if line_length_sq == 0:
# Line is actually a point
return math.hypot(px - x1, py - y1)

# Parameter t for closest point on line
t = max(0, min(1, ((px - x1) * (x2 - x1) + (py - y1) * (y2 - y1)) / line_length_sq))

# Closest point on line
closest_x = x1 + t * (x2 - x1)
closest_y = y1 + t * (y2 - y1)

# Distance from point to closest point
return math.hypot(px - closest_x, py - closest_y)

# Test distance calculation
point = (2, 2)
line_start, line_end = (0, 0), (4, 0)
distance = distance_point_to_line(point, line_start, line_end)
print(f"Distance from {point} to line: {distance}") # 2.0

Performance Considerations

Time Complexity Summary

Operation CategoryTime ComplexityNotes
Basic arithmetic (sqrt, pow, abs)O(1)Constant time operations
Trigonometric functionsO(1)Optimized implementations
Logarithmic functionsO(1)Hardware-optimized when available
factorial(n)O(n)Linear in input size
gcd(a, b)O(log(min(a,b)))Euclidean algorithm
comb(n, k)O(k)Optimized for small k
fsum(iterable)O(n)Linear in number of elements

Basic Benchmarking

import math
import timeit

# Compare math functions vs built-in operations
def benchmark_operations():
# Setup test data
test_numbers = list(range(1, 1000))

# Benchmark 1: Power operations
math_pow_time = timeit.timeit(lambda: [math.pow(x, 2) for x in test_numbers[:100]], number=1000)
builtin_pow_time = timeit.timeit(lambda: [x ** 2 for x in test_numbers[:100]], number=1000)

print(f"math.pow vs **: math.pow={math_pow_time:.4f}s, **={builtin_pow_time:.4f}s")

# Benchmark 2: Square root
math_sqrt_time = timeit.timeit(lambda: [math.sqrt(x) for x in test_numbers[:100]], number=1000)
pow_sqrt_time = timeit.timeit(lambda: [x ** 0.5 for x in test_numbers[:100]], number=1000)

print(f"math.sqrt vs **0.5: sqrt={math_sqrt_time:.4f}s, **0.5={pow_sqrt_time:.4f}s")

# Benchmark 3: Sum operations
builtin_sum_time = timeit.timeit(lambda: sum([0.1] * 100), number=1000)
math_fsum_time = timeit.timeit(lambda: math.fsum([0.1] * 100), number=1000)

print(f"sum vs math.fsum: sum={builtin_sum_time:.4f}s, fsum={math_fsum_time:.4f}s")

# Run benchmarks
benchmark_operations()

# Performance comparison for specific use cases
def compare_distance_calculations():
points1 = [(i, i+1) for i in range(100)]
points2 = [(i+2, i+3) for i in range(100)]

# Method 1: Using math.sqrt
def distance_sqrt():
return [math.sqrt((p1[0]-p2[0])**2 + (p1[1]-p2[1])**2)
for p1, p2 in zip(points1, points2)]

# Method 2: Using math.hypot
def distance_hypot():
return [math.hypot(p1[0]-p2[0], p1[1]-p2[1])
for p1, p2 in zip(points1, points2)]

sqrt_time = timeit.timeit(distance_sqrt, number=1000)
hypot_time = timeit.timeit(distance_hypot, number=1000)

print(f"Distance calculation: sqrt={sqrt_time:.4f}s, hypot={hypot_time:.4f}s")

compare_distance_calculations()

Memory Usage Tips

import math
import sys

# Memory-efficient patterns
def memory_efficient_calculations():
# Use math.fsum for large sequences instead of sum
# fsum uses less memory for intermediate calculations
large_numbers = (i * 0.1 for i in range(1000000)) # Generator
result = math.fsum(large_numbers) # Memory efficient

# Use math.prod for products (Python 3.8+)
small_numbers = range(1, 11)
product = math.prod(small_numbers) # More efficient than reduce

# Avoid creating large factorial intermediates
def efficient_combination(n, k):
"""Calculate combination without computing full factorials."""
if k > n - k: # Take advantage of symmetry
k = n - k
return math.perm(n, k) // math.factorial(k)

# For very large n, use math.comb directly
large_comb = math.comb(1000, 3) # Efficient implementation

return result, product, large_comb

# Avoid memory issues with large calculations
def safe_large_calculations(n):
"""Demonstrate safe patterns for large calculations."""
# Use logarithms for very large products
if n > 170: # factorial(170) is near float limit
# Use lgamma instead of factorial for large n
log_factorial = math.lgamma(n + 1)
return f"log(n!) = {log_factorial}"
else:
return math.factorial(n)

print(f"Large calculation result: {safe_large_calculations(100)}")
print(f"Very large calculation: {safe_large_calculations(200)}")

🎯 When to Use math

✅ Ideal Use Cases

  • Mathematical algorithm implementations requiring precise floating-point operations
  • Geometric computations involving trigonometry, distances, and coordinate transformations
  • Number theory problems needing GCD, LCM, factorials, and combinatorics
  • Scientific calculations requiring special functions (gamma, error functions)
  • Floating-point precision handling where accuracy is critical
  • Performance-critical mathematical operations (optimized C implementations)
  • Cross-platform mathematical consistency (IEEE 754 compliance)
  • Algorithm implementations requiring mathematical constants (π, e, τ)

❌ When NOT to Use math

  • Complex number operations (use cmath module instead)
  • Arbitrary precision arithmetic (use decimal or fractions modules)
  • Statistical operations on datasets (use statistics module)
  • Matrix operations and linear algebra (use numpy for non-stdlib)
  • Symbolic mathematics (use sympy for non-stdlib)
  • Random number generation (use random module)
  • Simple integer arithmetic where built-in operators suffice
  • Financial calculations requiring exact decimal representation

Alternative Solutions

import math
import decimal
import fractions
import cmath

# Alternative 1: For exact decimal arithmetic
decimal.getcontext().prec = 50
exact_result = decimal.Decimal('1') / decimal.Decimal('3')
print(f"Exact decimal: {exact_result}")

# Alternative 2: For rational arithmetic
rational = fractions.Fraction(1, 3)
print(f"Rational: {rational}")

# Alternative 3: For complex numbers
complex_sqrt = cmath.sqrt(-1)
print(f"Complex sqrt(-1): {complex_sqrt}")

# Alternative 4: When built-ins are sufficient
# Instead of math.pow(2, 3) for integers
simple_power = 2 ** 3 # Faster for integer operations

# Alternative 5: For statistical operations
# Instead of implementing mean with math.fsum
import statistics
data = [1, 2, 3, 4, 5]
mean = statistics.mean(data) # More appropriate

Migration Strategies

# Migrating from basic operations to math module
def migrate_to_math_module():
"""Examples of when to migrate to math module."""

# Before: Using ** for all power operations
def old_distance(p1, p2):
return ((p1[0] - p2[0]) ** 2 + (p1[1] - p2[1]) ** 2) ** 0.5

# After: Using math for better precision and performance
def new_distance(p1, p2):
return math.hypot(p1[0] - p2[0], p1[1] - p2[1])

# Before: Manual floating-point comparison
def old_compare(a, b):
return abs(a - b) < 1e-9

# After: Using math.isclose for robust comparison
def new_compare(a, b):
return math.isclose(a, b, rel_tol=1e-9)

# Before: Implementing own GCD
def old_gcd(a, b):
while b:
a, b = b, a % b
return a

# After: Using optimized math.gcd
def new_gcd(a, b):
return math.gcd(a, b)

return old_distance, new_distance, old_compare, new_compare

Additional Learning Resources

Official Python Resources (PRIMARY SOURCES)

Books and Publications

  • "Fluent Python" by Luciano Ramalho - Chapter on numeric types and precision
  • "Effective Python" by Brett Slatkin - Best practices for numeric operations
  • "Numerical Python" by Robert Johansson - Mathematical computing in Python
  • "Python Tricks" by Dan Bader - Practical examples of math module usage

Online Tutorials and Courses

Practice and Examples

  • LeetCode: Mathematical problems requiring precise calculations
  • HackerRank: Mathematics domain challenges
  • Project Euler: Mathematical programming problems
  • Codewars: Math-focused Python katas

Advanced Topics

  • IEEE 754 Standard: Understanding floating-point representation
  • Numerical Methods: Implementing mathematical algorithms
  • Computer Graphics: Trigonometry and geometric transformations
  • Cryptography: Number theory applications

Community Resources

  • r/Python: Mathematical computing discussions
  • r/learnpython: Math module questions and examples
  • Stack Overflow: python-math tag

This documentation follows the Python Standard Library Reference style and includes examples adapted from the official Python documentation. For the most up-to-date information, always refer to the official Python documentation.