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.
High because floating-point intermediates in chained calculations produce non-deterministic results that break financial reconciliation and audit trails.
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.
ID: finserv-form-validation.currency-amount.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 += interest where balance is 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.ts or 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 compound
Good (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)