Unit-Aware Arithmetic (Python)
A type-safe dimensional arithmetic library that tracks units at runtime and prevents invalid operations.
Features
- ✅ Type-safe dimensional analysis: Prevents incompatible unit operations
- ✅ Zero dependencies: Core functionality has no external dependencies
- ✅ Comprehensive unit coverage: SI, imperial, and derived units
- ✅ Arithmetic operations: Add, subtract, multiply, divide with unit tracking
- ✅ Unit conversion: Automatic and explicit conversion between compatible units
- ✅ Clear error messages: Helpful errors for incompatible operations
- ✅ Production-ready: Comprehensive test coverage (>95%)
Installation
pip install -e .
Quick Start
from dimensional import Quantity, units
# Create quantities with units
distance = Quantity(100, units.meter)
time = Quantity(9.58, units.second)
# Arithmetic operations with automatic unit tracking
speed = distance / time
print(speed) # 10.438413361169102 m/s
# Unit conversion
distance_km = distance.to(units.kilometer)
print(distance_km) # 0.1 km
# Type-safe operations - this will raise an error!
try:
distance + time # IncompatibleUnitsError
except Exception as e:
print(f"Error: {e}")
Usage Examples
Basic Arithmetic
from dimensional import Quantity, units
# Addition (same dimension required)
d1 = Quantity(5, units.meter)
d2 = Quantity(3, units.meter)
total = d1 + d2 # 8.0 m
# Multiplication creates derived units
area = Quantity(5, units.meter) * Quantity(3, units.meter)
print(area) # 15.0 m·m
# Division creates derived units
velocity = Quantity(100, units.meter) / Quantity(10, units.second)
print(velocity) # 10.0 m/s
Unit Conversion
from dimensional import Quantity, units
# Length conversion
distance = Quantity(1, units.mile)
distance_km = distance.to(units.kilometer)
print(distance_km) # 1.60934 km
# Temperature conversion
temp_c = Quantity(0, units.celsius)
temp_k = temp_c.to(units.kelvin)
print(temp_k) # 273.15 K
# Mass conversion
mass_lb = Quantity(10, units.pound)
mass_kg = mass_lb.to(units.kilogram)
print(mass_kg) # 4.53592 kg
Physics Calculations
from dimensional import Quantity, units
# Calculate velocity
distance = Quantity(100, units.meter)
time = Quantity(9.58, units.second)
velocity = distance / time
print(f"Velocity: {velocity}")
# Calculate force (F = ma)
mass = Quantity(10, units.kilogram)
acceleration = Quantity(9.8, units.meter_per_second_squared)
force = mass * acceleration
print(f"Force: {force}")
# Calculate kinetic energy (KE = 1/2 * m * v²)
mass = Quantity(2, units.kilogram)
velocity = Quantity(10, units.meter_per_second)
ke = 0.5 * mass * (velocity ** 2)
print(f"Kinetic Energy: {ke}")
Comparison Operations
from dimensional import Quantity, units
d1 = Quantity(100, units.centimeter)
d2 = Quantity(1, units.meter)
# Automatic conversion for comparison
print(d1 == d2) # True
print(d1 < Quantity(2, units.meter)) # True
# `==` is strict exact equality (after conversion to a common unit).
# For approximate comparison within a tolerance, use `is_close`:
print(Quantity(1, units.meter).is_close(Quantity(1.0000001, units.meter), rel_tol=1e-6)) # True
print(Quantity(0, units.meter).is_close(Quantity(1e-12, units.meter), abs_tol=1e-9)) # True
Available Units
Length
meter,kilometer,centimeter,millimeterinch,foot,yard,mile
Mass
kilogram,gram,milligram,tonnepound,ounce
Time
second,minute,hour,day
Temperature
kelvin,celsius,fahrenheit
Current
ampere,milliampere
Chemistry
mole
Derived Units
newton(force)joule,kilojoule(energy)calorie,kilocalorie,watt_hour(energy)watt,kilowatt(power)pascal,kilopascal(pressure)meter_per_second,kilometer_per_hour,mile_per_hour(velocity)meter_per_second_squared(acceleration)square_meter,square_kilometer,hectare(area)cubic_meter,liter,milliliter(volume)hertz,kilohertz,megahertz(frequency)radian,degree,arcminute,arcsecond(angle)volt,ohm(electricity)
Error Handling
The library provides clear error messages for invalid operations:
from dimensional import Quantity, units, IncompatibleUnitsError, AffineUnitArithmeticError
distance = Quantity(100, units.meter)
time = Quantity(10, units.second)
try:
# This will raise IncompatibleUnitsError
result = distance + time
except IncompatibleUnitsError as e:
print(e) # "Cannot add m and s: incompatible dimensions"
try:
# This will raise AffineUnitArithmeticError
result = Quantity(2, units.celsius) * Quantity(3, units.celsius)
except AffineUnitArithmeticError as e:
print(e) # "Cannot multiply affine units °C and °C; ..."
Testing
Run the test suite:
pytest test_dimensional.py -v
Run with coverage:
pytest test_dimensional.py --cov=dimensional --cov-report=html
Type Checking
This library includes type hints. Run type checking with:
mypy dimensional.py
Design Principles
- Zero Dependencies: Core functionality has no external dependencies
- Type Safety: Prevents invalid operations at runtime
- Clear Errors: Actionable error messages
- Production Ready: Comprehensive test coverage
- Performance: Efficient implementation with minimal overhead
API Reference
Dimension
Represents the dimensional formula of a unit (e.g., L^1 T^-2 for acceleration).
Unit
Represents a unit of measurement with its dimension and conversion factor.
Quantity
A numeric value with an associated unit. Supports:
- Arithmetic:
+,-,*,/,**,-(negation),abs() - Comparison:
==,!=,<,<=,>,>=(==is strict exact equality after conversion to a common unit) - Approximate comparison:
.is_close(other, rel_tol=1e-9, abs_tol=0.0) - Conversion:
.to(target_unit)(returnsQuantity);.value_in(target_unit)(returns the rawfloatvalue)
units
Namespace containing all predefined units.
License
MIT License
Contributing
Contributions are welcome! Please ensure:
- All tests pass
- Code coverage remains >90%
- Type hints are included
- Documentation is updated
Changelog
2.0.0 (2026-09-06)
- Added angle units:
radian,degree,arcminute,arcsecond - Added frequency units:
kilohertz,megahertz - Added area units:
square_kilometer,hectare - Added volume units:
liter,milliliter - Added velocity unit:
mile_per_hour - Added chemistry unit:
mole - Added energy units:
calorie,kilocalorie,watt_hour - Added electricity units:
volt,ohm - Updated canonical-unit lookup table to canonicalize Hz, m², m³, V, and Ω
1.0.0 (2026-08-28)
- Initial release
- Support for SI and imperial units
- Comprehensive dimensional analysis
- Temperature conversion with offset handling
- Full test coverage
Metadata
Release files for unit-aware-arithmetic 2.0.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| unit_aware_arithmetic-2.0.0.tar.gz | 13.6 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| unit_aware_arithmetic-2.0.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 24.6 kB
Release files / unit_aware_arithmetic-2.0.0.tar.gz
| Download URL | unit_aware_arithmetic-2.0.0.tar.gz |
|---|---|
| Size | 13.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
a457c8963efa61d4ec375f26d32d20c4f13f27034a3aedb05ed2d778aa4b08ac
|
|
BLAKE2b-256 checksum How to use checksums |
11fc9a1cb568879e91f9b217bcf602ba2b01545ff3290fb033f198556a58c59f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.5
|
Release files / unit_aware_arithmetic-2.0.0-py3-none-any.whl
| Download URL | unit_aware_arithmetic-2.0.0-py3-none-any.whl |
|---|---|
| Size | 11.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
7c24968707d0a5d56c05ab6c37bdef6db33b15bb844ad16c28405d03dc4ad29a
|
|
BLAKE2b-256 checksum How to use checksums |
8ab463e9dfbcf17459feb5c58df249462e2ced0a99e60593e1d2957b4bcffc22
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.5
|
Security for unit-aware-arithmetic 2.0.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.