All files round.ts

100% Statements 12/12
100% Branches 5/5
100% Functions 1/1
100% Lines 11/11

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28                        3x 125x 123x 123x 123x 123x 123x   123x 8x   115x   123x    
/**
 * Round `value` to `dp` decimal places using decimal half-even (round half to
 * even / banker's rounding) so it mirrors the server's `Decimal(round(x, n))`.
 *
 * This intentionally matches Python's *decimal* half-even behaviour, NOT Python
 * float `round()` (e.g. `roundHalfEven(2.675, 2) === 2.68`, whereas float
 * `round(2.675, 2)` yields 2.67).
 *
 * Targeted at the money domain: small magnitudes and `dp <= 3`. The `EPS`
 * half-detection tolerance is tuned for that domain and is not intended for
 * arbitrary large magnitudes or high precision.
 */
export function roundHalfEven(value: number, dp: number): number {
  if (!isFinite(value)) return value;
  const factor = Math.pow(10, dp);
  const scaled = value * factor;
  const floor = Math.floor(scaled);
  const diff = scaled - floor;
  const EPS = 1e-9;
  let rounded: number;
  if (Math.abs(diff - 0.5) < EPS) {
    rounded = floor % 2 === 0 ? floor : floor + 1;
  } else {
    rounded = Math.round(scaled);
  }
  return rounded / factor;
}