1,423 bytes · the TypeScript implementation · view raw
import { type RoundingMode } from"./math_round_div_types.ts";
/** * Divide two integers, rounding according to `mode`. * * Money is held in minor units (pence, cents) as integers. Every rate, * discount and tax calculation eventually needs to divide, and that division * is where rounding policy lives. Making it explicit here means a system can * state its policy once instead of scattering `Math.round` through a codebase. */exportfunction roundDiv(numerator: number, denominator: number, mode: RoundingMode = "half-up"): number {
if (!Number.isInteger(numerator) || !Number.isInteger(denominator)) {
thrownew TypeError("roundDiv operates on integers only");
}
if (denominator === 0) {
thrownew RangeError("denominator must not be zero");
}
const negative = numerator < 0 !== denominator < 0;
const n = Math.abs(numerator);
const d = Math.abs(denominator);
let quotient = Math.floor(n / d);
const remainder = n - quotient * d;
const twice = remainder * 2;
switch (mode) {
case"down":
break;
case"up":
if (remainder > 0) quotient += 1;
break;
case"half-even":
if (twice > d || (twice === d && quotient % 2 === 1)) quotient += 1;
break;
case"half-up":
if (twice >= d) quotient += 1;
break;
default:
thrownew RangeError(`unknown rounding mode "${mode}"`);
}
return negative ? -quotient : quotient;
}