Skip to main content
Back to module
Scientific Python · Units and Data Files

Units-aware calculations

Reading40mLesson 1 of 3 in this module

Carry units through a calculation by converting to SI at the edges, checking dimensions, and using a units library such as pint.

Why this matters

In 1999 NASA lost the Mars Climate Orbiter because one team's software reported thruster impulse in pound-force seconds while the navigation software expected newton seconds. Every number was computed correctly; the units were not. Smaller versions of that mistake happen every day: a pressure in kPa used as if it were Pa, a flow in L/min mixed with m³/s, a drawing in millimetres read as inches, a concentration in mg/L confused with mmol/L. Python's floats carry no units, so you have to.

Strategy 1: convert to SI at the edges

The simplest reliable habit: convert every input to SI base units (m, kg, s, A, K, mol) as soon as it enters your code, compute in SI, and convert back only for output.

MM = 1e-3          # metres per millimetre
KPA = 1e3          # pascals per kilopascal
MIN = 60.0         # seconds per minute
L = 1e-3           # cubic metres per litre

d = 25 * MM                    # pipe diameter, m
flow = 40 * L / MIN            # 40 L/min in m^3/s
area = 3.14159 * d**2 / 4      # m^2
velocity = flow / area         # m/s
print(f"{velocity:.2f} m/s")   # 1.36 m/s

Naming the constants (MM, KPA) makes the conversions readable and searchable. Put units in variable names or comments when they are not SI: temp_C, length_mm, pressure_kPa. Your future self will thank you.

Temperature is special: °C and K differ by an offset, not just a factor. A temperature difference of 10 °C is 10 K, but a temperature of 10 °C is 283.15 K. Formulas such as the ideal gas law and radiation need absolute temperatures.

Strategy 2: dimensional analysis

Every physical quantity has dimensions built from length L, mass M, time T, current I, temperature Θ and amount N. Force is M L T⁻²; energy is M L² T⁻²; pressure is M L⁻¹ T⁻². Three rules catch most unit errors:

  1. You can only add, subtract or compare quantities with the same dimensions. Adding a length to a time is a bug.
  2. Multiplying and dividing combine dimensions: exponents add and subtract.
  3. Arguments of exp, log and sin must be dimensionless. In e^(-t/τ), t and τ must share units.

You can check a formula on paper before you run it. For example, the kinetic energy ½ m v² has dimensions M (L T⁻¹)² = M L² T⁻², which is energy, as it should be.

Worked example: a tiny dimension checker

Representing dimensions as exponent tuples lets code enforce those rules:

class Q:
    def __init__(self, value, dims):       # dims = (L, M, T)
        self.value, self.dims = value, tuple(dims)

    def __mul__(self, other):
        return Q(self.value * other.value,
                 [a + b for a, b in zip(self.dims, other.dims)])

    def __add__(self, other):
        if self.dims != other.dims:
            raise ValueError(f"cannot add {self.dims} and {other.dims}")
        return Q(self.value + other.value, self.dims)

m = Q(1.0, (1, 0, 0)); s = Q(1.0, (0, 0, 1))
m + s        # ValueError: cannot add (1, 0, 0) and (0, 0, 1)

That is the core idea behind every units library.

Strategy 3: a units library (pint)

For real work, use a library. pint is the common choice in scientific Python:

import pint
ureg = pint.UnitRegistry()
Q_ = ureg.Quantity

force = 2.5 * ureg.kilonewton
area = (40 * ureg.mm) * (10 * ureg.mm)
stress = (force / area).to("MPa")
print(stress)                         # 6.25 megapascal

flow = 40 * ureg("L/min")
print(flow.to("m**3/s"))              # 0.000667 m³/s

T = Q_(25, ureg.degC).to("K")         # 298.15 kelvin (handles the offset)

(3 * ureg.m) + (2 * ureg.s)           # raises DimensionalityError

pint works with NumPy arrays (np.array([1, 2, 3]) * ureg.m), and .magnitude / .m_as("unit") give you the plain number when a function needs one. Other options are astropy.units (astronomy and physics) and unyt. pint is not loaded in this course's browser exercises, so the Do tab builds the dimension-checking idea yourself; install pint with pip install pint for local work.

Significant figures and reporting

Units come with precision. Report results with a sensible number of significant figures and the unit, 6.25 MPa, not 6.249999999 MPa or a bare 6.25. In tables, put the unit in the column header (Stress (MPa)).

Common mistakes

  • Mixing mm and m in one formula, especially in areas and volumes, where the error is a factor of 10⁶ or 10⁹.
  • °C in an absolute-temperature formula (ideal gas, Arrhenius, Stefan-Boltzmann).
  • Gauge versus absolute pressure (psig versus psia, or kPa(g) versus kPa(a)).
  • Degrees versus radians: np.sin(30) is the sine of 30 radians.
  • Pound-mass versus pound-force, and kWh versus kW.
  • Converting halfway through a calculation instead of at the edges.

Quick recap

  • Convert inputs to SI on entry, compute in SI, convert on output; name conversion constants.
  • Only add or compare quantities with equal dimensions; exp, log, sin need dimensionless arguments.
  • Use pint (or astropy.units) to make the computer enforce this; watch temperature offsets.
  • Report results with units and sensible precision.

Try it

In the Do tab you will finish a small Quantity class that tracks dimensions, then use it to compute a speed and a force and catch an illegal addition.

Also in this lesson: