round.js
Rounds numbers to the nearest multiple, with optional up or down direction control.
Repository Health
Technical Analysis
round is a small, focused JavaScript utility for rounding numbers to an arbitrary multiple rather than only to whole numbers or decimal places. Given a value and a multiple, it returns the nearest multiple, resolving ties by rounding up. An optional direction argument (up or down) forces the rounding behavior explicitly, and dedicated round.up() and round.down() convenience methods are provided for the common cases.
Internally it delegates precision-safe math to the round-precision and precision packages so that floating-point arithmetic quirks (like 0.1 + 0.2) don’t produce incorrect results when rounding to fractional multiples. This makes it useful anywhere values need to snap to a grid — currency rounding to the nearest denomination, UI layout snapping, quantity rounding to package sizes, or any domain where ‘nearest multiple of N’ matters more than ‘nearest integer’.
What You Get
- A
round(value, multiple, direction)function that rounds to the nearest multiple of any number, not just the nearest integer round.up(value, multiple)andround.down(value, multiple)convenience methods for explicit directional rounding- Floating-point-safe rounding via the
round-precisionandprecisiondependencies, avoiding classic JS decimal-math errors - A tiny, dependency-thin footprint (single-purpose module, no build step needed to consume it)
- Sensible tie-breaking (rounds up when a value is exactly equidistant between two multiples)
Common Use Cases
- Rounding prices or currency amounts to the nearest valid denomination (e.g. nearest 5 cents)
- Snapping UI measurements (grid sizes, spacing values) to a fixed step
- Rounding order quantities up or down to the nearest package/case size in e-commerce or inventory logic
- Normalizing sensor or measurement data to a fixed resolution before display or storage
Under The Hood
Architecture
round.js is a single-file module (index.js) with no internal layering: it exports one function, round(value, multiple, direction), plus two attached convenience methods, round.up and round.down, that call back into the same function with an explicit direction. A small internal methods lookup object maps the 'up'/'down' direction strings to Math.ceil/Math.floor, and an invalid direction string throws an explicit error rather than failing silently. When no direction is given, the function recursively calls itself once for up and once for down and picks whichever result is closer, with ties resolved toward up. There is no state, no configuration object, and nothing would break from a consumer’s perspective if the internal recursion were replaced with a direct computation — the module’s only real dependency-facing surface is the two packages it delegates to for the actual arithmetic.
Tech Stack
The module is plain, pre-ES6-style JavaScript ('use strict', var declarations) with no transpilation or bundling step — it ships as-is via npm and is consumed with a plain require('round'). Its only runtime dependencies are round-precision and precision (both pinned to ~1.0.0), which handle floating-point-safe rounding and precision detection so that fractional multiples don’t trigger classic JS decimal-arithmetic errors. Development tooling is standard for zero-config linting and tape for assertions, wired together through a single npm test script; a .travis.yml file shows the project once ran CI on Travis, though that pipeline is no longer active.
Code Quality
Testing is present but minimal: test.js uses tape to assert about a dozen input/output pairs covering default rounding, explicit up/down direction, the convenience methods, and a couple of floating-point edge cases (e.g. round(0.6123, 0.2)). There are no tests for the invalid-direction error path. Error handling is explicit in the one place it matters — an unrecognized direction string throws rather than silently defaulting — but there is no input validation for non-numeric value/multiple arguments. The standard linter is run as part of the test script, giving consistent style, but there are no TypeScript types or JSDoc annotations, and no active CI badge.
What Makes It Unique
The package doesn’t introduce a novel algorithm — it’s a straightforward wrapper around Math.ceil/Math.floor — but its niche value is bundling three things that are individually easy to get wrong: rounding to an arbitrary multiple (not just an integer), an explicit tie-breaking convention, and floating-point-safe precision handling via its two companion packages. That combination is what differentiates it from simply calling Math.round(value / multiple) * multiple inline, which is prone to floating-point drift for fractional multiples.