No cumulative floating-point errors in multi-step transactions
Why it matters
Floating-point errors in a single step are small; across a multi-step chain they compound unpredictably. A refund pipeline that subtracts a fee, applies a discount, and then taxes the result in float arithmetic will produce a different final amount depending on the order of operations — a determinism failure that makes reconciliation impossible. CWE-682 covers incorrect calculation; ISO 25010 functional-correctness requires financial outputs to be exact. Even a one-cent error per transaction becomes a material accounting discrepancy at tens of thousands of monthly transactions.
Severity rationale
High because floating-point intermediates in chained calculations produce non-deterministic results that break financial reconciliation and audit trails.
Remediation
Refactor all multi-step calculation chains to operate in integer cents from start to finish. Convert to cents once at the entry point and convert back to decimal only at display time.
// src/lib/finance.ts — integer arithmetic throughout
export function calculateRefund(
originalCents: number,
feeCents: number,
discountCents: number
): number {
// All intermediates remain integers
const afterFee = originalCents - feeCents;
const afterDiscount = afterFee - discountCents;
return Math.max(0, afterDiscount); // never negative
}
Search src/ for any pattern matching balance += or total -= where the variable is initialized as a float and replace with integer cent equivalents.
Detection
-
ID:
no-float-accumulation -
Severity:
high -
What to look for: Enumerate all multi-step financial calculation chains (transfers with fees, interest accrual loops, tax + subtotal sums, refund deductions). For each chain, count the number of arithmetic steps and classify whether intermediate values are integers (cents) or floats. Quote the accumulation pattern found (e.g.,
balance += interestwherebalanceis a float). Report: "X of Y multi-step chains use integer arithmetic throughout." -
Pass criteria: At least 100% of multi-step financial chains use integer (cents) arithmetic for all intermediate and final values. No more than 0 chains accumulate floating-point intermediates. Report even on pass: "X multi-step chains found, all using integer cents."
-
Fail criteria: Any multi-step chain uses float intermediates that are accumulated across at least 2 steps.
-
Do not pass when: A chain converts to cents at the end but performs intermediate calculations in floats — the accumulation damage occurs before the final conversion.
-
Skip (N/A) when: The project has no multi-step financial transactions (0 arithmetic chains with at least 2 steps found).
-
Detail on fail: Provide an example. Example:
"In refund processing, fee is subtracted from amount using floats: amount (22.50) - fee (2.50) = result (20.00). After 100s of such operations, rounding errors accumulate."or"Interest accrual loop: for each month, interest is added to balance as float and accumulated" -
Cross-reference: The integer-cents-storage check in this same category verifies the storage layer; this check verifies the computation layer stays in integer space.
-
Remediation: Always work with integers throughout the chain. In
src/lib/finance.tsor the relevant calculation module:Bad (float accumulation) — do NOT use:
let balance = 100.50; // float balance -= 2.30; // fee balance += 1.05; // interest balance -= 5.00; // withdrawal // balance = 94.25, but floating-point errors compoundGood (integer arithmetic) in
src/lib/finance.ts:let balanceCents = 10050; // integer balanceCents -= 230; // fee (integer cents) balanceCents += 105; // interest (integer cents) balanceCents -= 500; // withdrawal (integer cents) // balanceCents = 9425 (exact)
External references
- cwe · CWE-682 — Incorrect Calculation
- iso-25010:2011 · functional-correctness — Functional Suitability — Functional Correctness
Taxons
History
- 2026-04-18·v1.0.0·Initial import from finserv-form-validation·automated