# math.round-float Rounds a floating-point number to 0-12 decimal places, half away from zero, and returns the same double in TypeScript, Python and Rust. It is the one rounding step for everything in the registry that works in floats (chart geometry, colours, statistics that choose to use it), so "rounded to 2 decimal places" means the same thing everywhere. ## The rule The result is the multiple of 10^-decimals nearest to the **exact value of the double you passed**, with an exact tie going away from zero, and then the nearest double to that decimal. So: - `0.5` → `1`, `2.5` → `3`, `-2.5` → `-3`, `0.125` to 2 places → `0.13`. Those are exact binary values and true ties. Python's `round()` is half-even (2 and 0.12) and JavaScript's `Math.round` rounds -2.5 to -2. - `1.005` to 2 places → `1`, `2.675` → `2.67`, `1.45` to 1 place → `1.4`. None of those literals can be stored exactly; each is stored slightly below the tie (2.675 is 2.67499999999999982236...), so it rounds down. This matches JavaScript's `toFixed`. It does not match the shortcut `Math.round(x * 100) / 100`, which says 2.68, because `2.675 * 100` itself rounds to exactly 267.5 before `Math.round` sees it. - `8.345` → `8.35` and `0.0005` to 3 places → `0.001`: stored slightly above. - `0.49999999999999994` → `0`. `floor(x + 0.5)` says 1, because the addition rounds up to exactly 1. - The result is never `-0`: `-0.001` to 2 places is `0`, so it prints as `0`. When `|value| x 10^decimals` is 2^52 or more, the double has no digits left at that precision (the gap between neighbouring doubles is already that coarse), and it is returned unchanged. That is at most one unit in the last place from the correctly rounded decimal. ## Why all three languages agree The scaled value `|value| x 10^decimals` is computed once, its rounding error is recovered exactly with Dekker's TwoProduct (Veltkamp splitting; only `*` and `-`, so no fused multiply-add, which JavaScript lacks), and the tie is decided on their sum. Every step is an IEEE 754 operation the standard defines exactly, in the same order in each language; there is no library call whose last bit could differ. `stats.*` capabilities published before this one round the scaled product instead (`floor` of `|value| x 10^decimals`, then compare with a half), which agrees everywhere except on literals like 2.675 whose product lands exactly on a tie. New float capabilities should require this one rather than carry their own rounding. Sources: IEEE 754-2019 (correctly rounded +, -, *, /); T. J. Dekker, "A floating-point technique for extending the available precision", Numerische Mathematik 18 (1971) 224-242.