Python’s math module provides C-level mathematical functions for real numbers. import math. Constants: math.pi = π, math.e = e, math.tau = 2π, math.inf, math.nan. sqrt: math.sqrt(x) — faster than x**0.5. pow: math.pow(x, y) → float. exp: math.exp(x) = eˣ. log: math.log(x) = ln(x); math.log(x, base). log2/log10. ceil/floor/trunc: math.ceil(x), math.floor(x), math.trunc(x) → int. factorial: math.factorial(n). comb: math.comb(n, k) = C(n,k). perm: math.perm(n, k) = P(n,k). gcd: math.gcd(*integers) (3.9+ varargs). lcm: math.lcm(*integers) (Python 3.9+). isclose: math.isclose(a, b, rel_tol=1e-9, abs_tol=0.0). isfinite/isinf/isnan: float classification. fabs: math.fabs(x) → absolute value as float. copysign: math.copysign(x, y) — magnitude of x, sign of y. fsum: math.fsum(iterable) — accurate floating-point sum (no rounding accumulation). prod: math.prod(iterable, start=1) (Python 3.8+). hypot: math.hypot(*coords) — Euclidean distance (n-dimensional in 3.8+). atan2: math.atan2(y, x) — angle in radians. degrees/radians: conversion. modf: math.modf(x) → (fractional, integer) parts. frexp/ldexp: mantissa/exponent decomposition. erf/erfc/gamma/lgamma: special functions. Claude Code generates geometry calculators, statistical helpers, combinatorics solvers, and numerical analysis utilities.
CLAUDE.md for math
## math Stack
- Stdlib: import math
- Basic: math.sqrt(x) math.exp(x) math.log(x) math.log2(x)
- Round: math.floor/ceil/trunc(x) → int
- Combos: math.comb(n, k) math.factorial(n) math.gcd(a, b)
- Float?: math.isclose(a, b, rel_tol=1e-9) math.isfinite(x)
- Trig: math.sin/cos/tan(radians) math.atan2(y, x) math.hypot(x, y)
- Exact Σ: math.fsum([0.1, 0.2, 0.3]) # avoids floating-point accumulation
math Numerical Computation Pipeline
# app/mathutil.py — numeric helpers, geometry, combinatorics, interpolation
from __future__ import annotations
import math
from collections.abc import Iterable
from dataclasses import dataclass
from typing import NamedTuple
# ─────────────────────────────────────────────────────────────────────────────
# 1. Numeric helpers
# ─────────────────────────────────────────────────────────────────────────────
def clamp(value: float, lo: float, hi: float) -> float:
"""
Clamp value to [lo, hi].
Example:
clamp(150.0, 0.0, 100.0) # 100.0
clamp(-5.0, 0.0, 100.0) # 0.0
"""
return max(lo, min(hi, value))
def lerp(a: float, b: float, t: float) -> float:
"""
Linear interpolation between a and b by fraction t ∈ [0, 1].
Example:
lerp(0.0, 10.0, 0.25) # 2.5
lerp(0.0, 10.0, 1.0) # 10.0
"""
return a + (b - a) * t
def lerp_clamped(a: float, b: float, t: float) -> float:
"""Clamped lerp: t is forced into [0, 1]."""
return lerp(a, b, clamp(t, 0.0, 1.0))
def inv_lerp(a: float, b: float, value: float) -> float:
"""
Inverse linear interpolation: return t such that lerp(a, b, t) == value.
Returns 0 if a == b (degenerate segment).
Example:
inv_lerp(0.0, 10.0, 2.5) # 0.25
"""
if math.isclose(a, b):
return 0.0
return (value - a) / (b - a)
def remap(
value: float,
in_min: float, in_max: float,
out_min: float, out_max: float,
) -> float:
"""
Remap value from [in_min, in_max] to [out_min, out_max].
Example:
remap(0.5, 0.0, 1.0, -1.0, 1.0) # 0.0
remap(255.0, 0.0, 255.0, 0.0, 1.0) # 1.0
"""
t = inv_lerp(in_min, in_max, value)
return lerp(out_min, out_max, t)
def safe_log(x: float, base: float = math.e, default: float = 0.0) -> float:
"""
Log of x, returning default if x <= 0.
Example:
safe_log(0.0) # 0.0 (default)
safe_log(100.0, 10.0) # 2.0
"""
if x <= 0:
return default
return math.log(x, base) if base != math.e else math.log(x)
def safe_div(a: float, b: float, default: float = 0.0) -> float:
"""Division returning default when b is zero or non-finite."""
if b == 0 or not math.isfinite(b):
return default
return a / b
def round_to(value: float, step: float) -> float:
"""
Round value to the nearest multiple of step.
Example:
round_to(3.7, 0.5) # 4.0
round_to(23.0, 5.0) # 25.0
"""
return round(value / step) * step
def sign(x: float) -> int:
"""Return -1, 0, or 1 based on the sign of x."""
if x > 0: return 1
if x < 0: return -1
return 0
def frac(x: float) -> float:
"""Return the fractional part of x (sign follows x)."""
return math.modf(x)[0]
def accurate_sum(values: Iterable[float]) -> float:
"""
Sum floating-point values accurately using math.fsum (no accumulation error).
Example:
accurate_sum([0.1] * 10) # 1.0 exactly (vs sum() → 0.9999999...)
"""
return math.fsum(values)
# ─────────────────────────────────────────────────────────────────────────────
# 2. Geometry helpers
# ─────────────────────────────────────────────────────────────────────────────
class Vec2(NamedTuple):
x: float
y: float
def distance(a: Vec2, b: Vec2) -> float:
"""Euclidean distance between two 2-D points."""
return math.hypot(b.x - a.x, b.y - a.y)
def manhattan_distance(a: Vec2, b: Vec2) -> float:
"""Manhattan (L1) distance."""
return math.fabs(b.x - a.x) + math.fabs(b.y - a.y)
def angle_between(a: Vec2, origin: Vec2, b: Vec2) -> float:
"""
Angle in degrees at origin between rays origin→a and origin→b.
Example:
angle_between(Vec2(1,0), Vec2(0,0), Vec2(0,1)) # 90.0
"""
ax, ay = a.x - origin.x, a.y - origin.y
bx, by = b.x - origin.x, b.y - origin.y
dot = ax * bx + ay * by
det = ax * by - ay * bx
return math.degrees(math.atan2(abs(det), dot))
def rotate_point(p: Vec2, origin: Vec2, degrees: float) -> Vec2:
"""Rotate p around origin by degrees."""
rad = math.radians(degrees)
cos_a, sin_a = math.cos(rad), math.sin(rad)
dx, dy = p.x - origin.x, p.y - origin.y
return Vec2(
origin.x + dx * cos_a - dy * sin_a,
origin.y + dx * sin_a + dy * cos_a,
)
def circle_area(r: float) -> float:
return math.pi * r * r
def circle_circumference(r: float) -> float:
return math.tau * r
def sphere_volume(r: float) -> float:
return (4 / 3) * math.pi * r ** 3
def haversine_km(lat1: float, lon1: float, lat2: float, lon2: float) -> float:
"""
Great-circle distance in kilometers between two WGS-84 coordinates.
Example:
d = haversine_km(51.5, -0.1, 48.85, 2.35) # London → Paris ≈ 340 km
"""
R = 6_371.0
φ1, φ2 = math.radians(lat1), math.radians(lat2)
dφ = math.radians(lat2 - lat1)
dλ = math.radians(lon2 - lon1)
a = math.sin(dφ / 2) ** 2 + math.cos(φ1) * math.cos(φ2) * math.sin(dλ / 2) ** 2
return R * 2 * math.atan2(math.sqrt(a), math.sqrt(1 - a))
# ─────────────────────────────────────────────────────────────────────────────
# 3. Combinatorics and number theory
# ─────────────────────────────────────────────────────────────────────────────
def combinations(n: int, k: int) -> int:
"""C(n, k) — binomial coefficient."""
return math.comb(n, k)
def permutations(n: int, k: int) -> int:
"""P(n, k) — ordered selections."""
return math.perm(n, k)
def is_prime(n: int) -> bool:
"""
Trial-division primality test (suitable for n < 10^9).
Example:
is_prime(97) # True
is_prime(100) # False
"""
if n < 2:
return False
if n == 2:
return True
if n % 2 == 0:
return False
for i in range(3, math.isqrt(n) + 1, 2):
if n % i == 0:
return False
return True
def primes_up_to(n: int) -> list[int]:
"""Sieve of Eratosthenes: return all primes ≤ n."""
if n < 2:
return []
sieve = bytearray([1]) * (n + 1)
sieve[0] = sieve[1] = 0
for i in range(2, math.isqrt(n) + 1):
if sieve[i]:
sieve[i*i::i] = bytearray(len(sieve[i*i::i]))
return [i for i, v in enumerate(sieve) if v]
def gcd(*ns: int) -> int:
"""GCD of two or more integers."""
return math.gcd(*ns)
def lcm(*ns: int) -> int:
"""LCM of two or more integers."""
return math.lcm(*ns)
def digits_of(n: int, base: int = 10) -> list[int]:
"""
Return list of digits of |n| in the given base (most significant first).
Example:
digits_of(255, 2) # [1, 1, 1, 1, 1, 1, 1, 1]
digits_of(255, 16) # [15, 15]
"""
n = abs(n)
if n == 0:
return [0]
result = []
while n:
result.append(n % base)
n //= base
return result[::-1]
def digit_sum(n: int) -> int:
"""Return the sum of decimal digits of |n|."""
return sum(int(d) for d in str(abs(n)))
# ─────────────────────────────────────────────────────────────────────────────
# 4. Float safety and comparison
# ─────────────────────────────────────────────────────────────────────────────
def approx_equal(a: float, b: float, tol: float = 1e-9) -> bool:
"""Relative + absolute tolerance float comparison."""
return math.isclose(a, b, rel_tol=tol, abs_tol=tol)
def is_integer_valued(x: float) -> bool:
"""Return True if x is a whole number (e.g., 3.0, -5.0)."""
return math.isfinite(x) and math.floor(x) == x
def nan_to_default(x: float, default: float = 0.0) -> float:
"""Replace NaN with default."""
return default if math.isnan(x) else x
def clamp_finite(x: float, lo: float = -1e308, hi: float = 1e308) -> float:
"""Clamp and replace any non-finite value with lo or hi."""
if not math.isfinite(x):
return hi if x > 0 else lo
return clamp(x, lo, hi)
# ─────────────────────────────────────────────────────────────────────────────
# Demo
# ─────────────────────────────────────────────────────────────────────────────
if __name__ == "__main__":
print("=== math demo ===")
print("\n--- numeric helpers ---")
print(f" clamp(150, 0, 100) = {clamp(150.0, 0.0, 100.0)}")
print(f" lerp(0, 10, 0.25) = {lerp(0.0, 10.0, 0.25)}")
print(f" inv_lerp(0, 10, 2.5) = {inv_lerp(0.0, 10.0, 2.5)}")
print(f" remap(0.5, 0,1, -1,1) = {remap(0.5, 0.0, 1.0, -1.0, 1.0)}")
print(f" round_to(3.7, 0.5) = {round_to(3.7, 0.5)}")
print(f" sign(-7) = {sign(-7)}")
print(f" frac(3.75) = {frac(3.75)}")
print(f" accurate_sum([0.1]*10) = {accurate_sum([0.1]*10)}")
print(f" builtin sum [0.1]*10 = {sum([0.1]*10)}")
print("\n--- geometry ---")
a, b = Vec2(0, 0), Vec2(3, 4)
print(f" distance (0,0)→(3,4) = {distance(a, b)}")
print(f" manhattan same = {manhattan_distance(a, b)}")
print(f" circle_area(r=5) = {circle_area(5):.4f}")
print(f" sphere_volume(r=1) = {sphere_volume(1):.4f}")
print(f" haversine London→Paris = {haversine_km(51.5, -0.1, 48.85, 2.35):.1f} km")
r = rotate_point(Vec2(1, 0), Vec2(0, 0), 90.0)
print(f" rotate (1,0) by 90° = ({r.x:.6f}, {r.y:.6f})")
print("\n--- combinatorics ---")
print(f" C(10, 3) = {combinations(10, 3)}")
print(f" P(10, 3) = {permutations(10, 3)}")
print(f" gcd(12, 18) = {gcd(12, 18)}")
print(f" lcm(4, 6) = {lcm(4, 6)}")
print(f" factorial(10) = {math.factorial(10):,}")
print(f" is_prime(97) = {is_prime(97)}")
print(f" primes ≤ 50 = {primes_up_to(50)}")
print(f" digits(255, 2) = {digits_of(255, 2)}")
print(f" digit_sum(12345) = {digit_sum(12345)}")
print("\n--- float safety ---")
print(f" isclose(0.1+0.2, 0.3) = {math.isclose(0.1+0.2, 0.3)}")
print(f" isfinite(inf) = {math.isfinite(math.inf)}")
print(f" isnan(nan) = {math.isnan(math.nan)}")
print(f" nan_to_default(nan) = {nan_to_default(math.nan)}")
print(f" clamp_finite(inf) = {clamp_finite(math.inf)}")
print("\n--- math constants ---")
print(f" pi = {math.pi}")
print(f" e = {math.e}")
print(f" tau = {math.tau}")
print("\n=== done ===")
For the cmath alternative — cmath provides the same functions as math but operating on complex numbers: cmath.sqrt(-1) → 1j, cmath.exp(1j * math.pi) ≈ -1+0j (Euler’s formula); math raises ValueError for inputs that produce complex results — use cmath explicitly when your domain includes complex numbers (signal processing, electrical engineering, quantum mechanics); use math for all real-valued computation, where it is faster and produces clearer error messages on invalid inputs. For the numpy alternative — numpy vectorizes math operations across whole arrays with BLAS/LAPACK acceleration: np.sqrt(array), np.sin(array), np.log(array) — no Python-level loops; math operates on single scalars and is faster for one value at a time but has no array broadcasting — use numpy when you process arrays, matrices, or sequences of numbers; use math for scalar calculations in business logic, CLI tools, and environments where NumPy is unavailable or would be an unnecessary dependency. The Claude Skills 360 bundle includes math skill sets covering clamp()/lerp()/inv_lerp()/remap() interpolation utilities, safe_log()/safe_div()/round_to()/accurate_sum() numeric safety helpers, Vec2/distance()/haversine_km()/rotate_point() geometry, combinations()/permutations()/is_prime()/primes_up_to()/gcd()/lcm() combinatorics, and approx_equal()/nan_to_default()/clamp_finite() float safety. Start with the free tier to try numerical computation patterns and math pipeline code generation.