Skip to content
Basic

exact_units exact_units

exact_units

Units of measure fixed at compile time, exact.

A number carries its unit, its scale and its storage in its type. The compiler checks them. At run time it is just the integer.

use exact_units::{Fixed, Micros, prefix::Milli};

let t: Micros<u32> = Fixed::new(1500);        // 1500 µs, stored as a u32
assert_eq!(t.to_string(), "1500 µs");
assert_eq!(t.to::<Milli, u16>(), None);        // not a whole number of ms: refused
assert_eq!(size_of::<Micros<u32>>(), 4);       // the same bytes as the u32

What it is for

  • Firmware and device APIs that keep numbers as integers: µs timers, mV readings, Q15 samples, binary angles.
  • Conversions that are exact or refused, never rounded through a float.
  • The cases other unit crates leave out: temperatures as points, angles that wrap, levels in dB, counted things.

How to read this book

The book goes from easy to deep. Each page has a badge with its reading level.

  1. Why: what goes wrong with a plain u32, and what the type fixes.
  2. First steps: Fixed, units, prefixes, printing, literals.
  3. Doing maths: arithmetic, conversions, bounds, rounding, overflow.
  4. Fixed point: Q15, Q31 and binary angles for DSP and motor control.
  5. Points: temperatures, angles that wrap, sensor register formulas, indices.
  6. Levels: dB and neper, thresholds as integer compares.
  7. Complex: impedances, IQ samples, CORDIC.
  8. Your units: customary units, and units of your own.
  9. The wire: the same bytes on the wire, the unit in the API.
  10. Nomicon: exact magnitudes, how conversions are chosen, how the crate is tested.

The recipes are short answers to common tasks.

Add it

[dependencies]
exact_units = "0.1"

A firmware picks only what it uses: see On a microcontroller.

The API reference is on docs.rs. The source is on GitHub.