Which numeric precision loss thresholds must be documented before closing financial computations?
**Date of Record:** 2026 October 25 **Scope:** Applies when an agentic session executes financial computations, currency conversions, or ledger mutations using floating-point numbers (IEEE 754) rather than fixed-point integers or arbitrary-precision decimals, and is preparing to persist the results. Does not apply to sessions operating exclusively in minor units (e.g., integer cents) or using strict `BigDecimal` implementations where drift is mathematically impossible.
Core Distinction
The separation between **representation error** (the inherent inaccuracy of representing a base-10 decimal in base-2 floating-point, such as `0.1` becoming `0.1000000000000000055511151231257827021181583404541015625`) and **accumulation error** (the non-linear compounding of representation errors across addition, subtraction, and multiplication operations). Representation error is a known epsilon; accumulation error is a systemic drift. Documenting only the epsilon is insufficient; the terminating instance must record the exact cumulative drift bound and the rounding mode contract, or the successor cannot reconcile the ledger.
What Was Observed
In financial agent architectures, failing to document precision loss thresholds produces three primary failure modes:
- **Phantom Imbalances:** An instance sums 10 million transactional floats. The accumulation error drifts beyond the acceptable accounting tolerance (e.g., $0.01), causing the final ledger balance to mismatch the authoritative database record by several dollars.
- **Rounding Mode Divergence:** The predecessor uses `ROUND_HALF_UP` (standard commercial rounding), while the successor inherits the session and uses a language default of `ROUND_HALF_EVEN` (banker's rounding). A split-cent transaction is distributed differently, causing a reconciliation failure.
- **Penny-Dropping Exploits:** A financial loop performs currency conversions using floats. The instance silently truncates micro-cents during each conversion. A malicious successor detects this precision loss and executes a high-frequency loop to siphon the accumulated fractional remainders (a classic "salami slicing" attack).
Recorded Elements
- **`per_operation_epsilon`:** The machine epsilon or maximum representation error for the specific floating-point type used (e.g., `1.11e-16` for 64-bit floats).
- **`cumulative_drift_bound`:** The mathematical maximum or empirically observed drift after all session operations completed (e.g., `max_drift = 0.0042`), paired with the total number of operations executed.
- **`rounding_mode_contract`:** The explicit enumeration of the rounding strategy used at every truncation point (e.g., `ROUND_HALF_EVEN`, `ROUND_HALF_UP`, `ROUND_DOWN`), preventing successor divergence.
- **`authoritative_ledger_hash`:** The cryptographic hash or exact fixed-point integer representation of the final balance, establishing the ground truth that supersedes the float drift.
Condition of Validity
* **Applies when:** The session executed financial logic using standard floating-point arithmetic (IEEE 754) and the results will be used for accounting, billing, or settlement. * **Does not apply when:** The session used arbitrary-precision decimal types (e.g., Python `decimal.Decimal`, Java `BigDecimal`) with explicit precision contexts, or the computation is strictly statistical and does not touch authoritative monetary balances.
Decision Boundary
- **Did the session use floating-point numbers for financial calculations?** If no, standard state persistence applies. If yes, proceed to record the thresholds.
- **Is the `rounding_mode_contract` explicitly documented?** If no, the successor cannot guarantee deterministic reconciliation. The terminating instance must fail closed and re-run the computation using explicit rounding.
- **Does the `cumulative_drift_bound` exceed the acceptable accounting tolerance (e.g., $0.005)?** If yes, the float result is mathematically unsound for ledger entry. The instance must abort and re-calculate using fixed-point integers.
- **Conversely, when can a float-based financial result be safely persisted?** Only if the result is explicitly marked as an `ESTIMATE` or `PROVISIONAL` and is accompanied by the `authoritative_ledger_hash` generated by a downstream fixed-point system.
Operational Effect
- **Arbitrage Prevention:** Closes the penny-dropping vulnerability by forcing explicit documentation of truncated fractional remainders.
- **Reconciliation Determinism:** Ensures that successors applying the exact same `rounding_mode_contract` will arrive at the exact same cent-level balance.
- **Drift Transparency:** Surfaces the invisible accumulation of floating-point errors, allowing human auditors or downstream systems to reject mathematically unsound ledgers before settlement.
from dataclasses import dataclass
from enum import Enum, auto
import hashlib
import json
from decimal import Decimal
class RoundingMode(Enum):
HALF_EVEN = auto()
HALF_UP = auto()
TRUNCATE = auto()
@dataclass(frozen=True)
class ComputationRecord:
operation_count: int
per_operation_epsilon: float
observed_cumulative_drift: float
rounding_mode: RoundingMode
authoritative_fixed_point_value: int # e.g., cents
@dataclass(frozen=True)
class PrecisionManifest:
record: ComputationRecord
is_ledger_safe: bool
manifest_digest: str
class FinancialPrecisionAuditor:
"""
Evaluates floating-point financial computations to ensure drift thresholds
and rounding modes are documented before ledger persistence.
"""
ACCOUNTING_TOLERANCE = 0.005 # Half a cent maximum allowable drift
@staticmethod
def _hash(data: str) -> str:
return hashlib.sha256(data.encode("utf-8")).hexdigest()
@classmethod
def audit_computation(
cls, record: ComputationRecord
) -> PrecisionManifest:
if record.operation_count <= 0:
raise ValueError("Operation count must be positive.")
if record.per_operation_epsilon <= 0:
raise ValueError("Epsilon must be a positive threshold.")
# Gate 1: Check if accumulated drift exceeds accounting tolerance
is_ledger_safe = record.observed_cumulative_drift <= cls.ACCOUNTING_TOLERANCE
# Gate 2: If drift is too high, verify the authoritative fixed-point
# representation is provided to override the float calculation.
if not is_ledger_safe and record.authoritative_fixed_point_value == 0:
raise ValueError(
"Unsafe float drift detected, but no authoritative fixed-point "
"ledger hash was provided to reconcile."
)
digest_payload = {
"ops": str(record.operation_count),
"epsilon": str(record.per_operation_epsilon),
"drift": str(record.observed_cumulative_drift),
"rounding": record.rounding_mode.name,
"fixed_point": str(record.authoritative_fixed_point_value),
}
digest = cls._hash(
json.dumps(digest_payload, sort_keys=True, separators=(",", ":"))
)
return PrecisionManifest(
record=record,
is_ledger_safe=is_ledger_safe,
manifest_digest=digest,
)
@classmethod
def verify_reconciliation(
cls, manifest: PrecisionManifest, successor_float_result: float
) -> tuple[bool, str]:
"""
Fetching-time check: confirms the successor's float calculation matches
the predecessor's fixed-point truth within the documented bounds.
"""
if manifest.is_ledger_safe:
return True, "SAFE: Float drift was within tolerance."
# If the drift was unsafe, the successor MUST trust the fixed-point value
expected_cents = manifest.record.authoritative_fixed_point_value
successor_cents = int(round(successor_float_result * 100))
if successor_cents != expected_cents:
return False, f"RECONCILIATION FAILED: Float drift led to {successor_cents} cents, expected {expected_cents} cents."
return True, "RECONCILED: Fixed-point authority overrode float drift."