numan 0.1.1

Humanize numbers: compact (1.2K), word (1.2 million) and SI metric (1.2 k) notation, plus parsing them back. Zero-dependency, no_std.
Documentation
  • Coverage
  • 100%
    19 out of 19 items documented4 out of 4 items with examples
  • Size
  • Source code size: 50.84 kB This is the summed size of all the files inside the crates.io package for this release.
  • Documentation size: 484.39 kB This is the summed size of all files generated by rustdoc for all configured targets
  • Ø build duration
  • this release: 1s Average build duration of successful builds.
  • all releases: 2s Average build duration of successful builds in releases after 2024-10-23.
  • Links
  • Homepage
  • trananhtung/numan
    0 0 0
  • crates.io
  • Dependencies
  • Versions
  • Owners
  • trananhtung

numan

All Contributors

Crates.io Documentation CI License no_std

Humanize numbers in Rust — turn raw numbers into the short, friendly strings you see in dashboards, CLIs and reports, and parse them back.

assert_eq!(numan::compact(1_234),       "1.2K");
assert_eq!(numan::word(1_200_000),      "1.2 million");
assert_eq!(numan::metric(1_500),        "1.5 k");
assert_eq!(numan::ordinal(22),          "22nd");
assert_eq!(numan::parse("1.5M").unwrap(), 1_500_000.0);

Zero dependencies. #![no_std] (needs only alloc). One small, focused crate.

Why numan?

Rust's ecosystem already humanizes file sizes (humansize) and relative time (chrono-humanize). What was missing is the part Python's humanize and Go's go-humanize are famous for: shortening the magnitude of plain numbers.

Need Reach for
File sizes (1.2 MiB) humansize
Relative time (3 hours ago) chrono-humanize
Number → words (forty-two) num2words
Locale thousands grouping num-format
Compact / word / metric magnitude (1.2K, 1.2 million, 1.2 k) + parsing numan

Install

[dependencies]
numan = "0.1"

Usage

Compact, word and metric notation

use numan::{compact, word, metric};

assert_eq!(compact(950),         "950");
assert_eq!(compact(12_300),      "12.3K");
assert_eq!(compact(1_500_000),   "1.5M");
assert_eq!(compact(-2_000_000),  "-2M");

assert_eq!(word(2_500),          "2.5 thousand");
assert_eq!(word(1_000_000),      "1 million");

assert_eq!(metric(1_000),        "1 k");   // SI: lowercase kilo
assert_eq!(metric(2_200_000),    "2.2 M");

Ordinals

assert_eq!(numan::ordinal(1),   "1st");
assert_eq!(numan::ordinal(112), "112th");

Parsing back

use numan::parse;

assert_eq!(parse("1.2K").unwrap(),       1_200.0);
assert_eq!(parse("1.5 million").unwrap(), 1_500_000.0);
assert_eq!(parse("-2.5bn").unwrap(),     -2_500_000_000.0);
assert_eq!(parse("1,234").unwrap(),       1_234.0); // separators ignored

Great for CLI flags like --limit 1.5M.

Fine-grained control with Formatter

use numan::Formatter;

let f = Formatter::compact().precision(2).space(true);
assert_eq!(f.format(1_234_567), "1.23 M");

// Keep trailing zeros, force an explicit sign:
let f = Formatter::compact().trim_zeros(false).sign_plus(true);
assert_eq!(f.format(1_000_000), "+1.0M");
Builder method Default Effect
precision(n) 1 Max fractional digits
trim_zeros(bool) true Drop trailing 0s and a dangling .
space(bool) per-notation Space between number and suffix
sign_plus(bool) false Prefix non-negatives with +

Behavior notes

  • Rounding uses Rust's standard round-half-to-even, and correctly carries into the next suffix (compact(999_950)"1M", never "1000K").
  • Beyond the table, compact (above a trillion) falls back to scientific notation (compact(1e36)"1e36"), which still round-trips through parse.
  • Non-finite floats render as "NaN", "inf", "-inf".
  • Negative zero (and negatives that round to zero) render as "0" — never "-0".
  • In parse, m/M means million (compact convention), never SI milli; SI exa (E) is not parsed, to avoid clashing with exponent notation (1e3), so metric output at exa returns an error rather than a wrong value.

no_std

numan is #![no_std] and only needs alloc (for String). It builds for bare-metal targets such as thumbv7em-none-eabi.

Contributors ✨

This project follows the all-contributors specification. Contributions of any kind are welcome — code, docs, bug reports, ideas, reviews! See the emoji key for how each contribution is recognized, and open a PR or issue to get involved.

Thanks goes to these wonderful people:

License

Licensed under either of Apache-2.0 or MIT at your option.