TUTORIALS 9 min read

Numeric Precision in Structured LLM Output: Stop Rounding From Becoming a Production Bug

Valid JSON can still corrupt money, measurements, IDs, and percentages. Design schemas and validators so an LLM never gets to improvise numeric precision.

By EgoistAI ·
Numeric Precision in Structured LLM Output: Stop Rounding From Becoming a Production Bug

Schema-constrained output solves syntax, not arithmetic. A model can return perfectly valid JSON while changing 19.995 to 20.00, expressing a 64-bit identifier in scientific notation, confusing a percentage with a fraction, or dropping the sign from a balance.

Once that payload reaches a payment, laboratory calculation, inventory system, or analytics pipeline, a plausible number becomes a production defect. Numeric safety requires representations and invariants that remove interpretation from the model.

Classify numbers before designing the schema

Do not use one generic number type for every domain. Classify fields by meaning:

  • money: currency plus amount in minor units or a decimal string;
  • counts: bounded integers with explicit minimums;
  • measurements: value, unit, precision, and observation context;
  • rates: fraction, percentage, or basis points—never an unlabeled decimal;
  • identifiers: strings, even when every character is numeric;
  • timestamps: validated ISO strings or integer epochs with a named unit.

The schema should make incompatible interpretations impossible.

{
  "amountMinor": 1999,
  "currency": "USD",
  "taxBasisPoints": 825,
  "accountId": "90071992547409931234"
}

This object does not ask downstream code whether 8.25 means a fraction or percent, and it prevents JavaScript from rounding the account identifier.

Keep identifiers out of floating-point types

JavaScript numbers cannot exactly represent every integer above 9,007,199,254,740,991. Other runtimes and databases have different limits. A model may reproduce a long numeric ID accurately as text, only for parsing to change its final digits.

Represent phone numbers, card references, order numbers, postal codes, and database keys as strings. Validate their format separately. Leading zeros and check digits are part of identity, not mathematical value.

If a tool contract already exposes unsafe numeric IDs, normalize them to strings at the adapter boundary before placing them in model context.

Choose a money representation deliberately

Binary floating point cannot exactly represent many decimal fractions. For fixed currencies, integer minor units are simple and reliable: $19.99 becomes 1999 cents. Currency must travel with the amount because minor-unit rules differ.

For arbitrary precision or assets with many decimal places, use a canonical decimal string and a decimal library. Define maximum scale and magnitude.

const Money = z.object({
  amount: z.string().regex(/^-?(0|[1-9]\d*)(\.\d{1,8})?$/),
  currency: z.enum(["USD", "EUR", "MYR", "BTC"]),
});

Do not let the model choose a rounding mode. The authoritative service should apply documented rules such as half-even or half-up at a specified step.

Separate extraction from calculation

Models are useful for locating a value in unstructured text and mapping it to a field. Deterministic code should perform arithmetic, currency conversion, tax calculation, aggregation, and threshold comparison.

Ask the model to return inputs and provenance:

{
  "quantity": "3",
  "unitPrice": "12.49",
  "currency": "USD",
  "sourceSpan": "3 units at $12.49 each"
}

Then compute the total with a decimal library. If the source is ambiguous, the model should return an explicit ambiguity state rather than invent a precision level.

Validate units and ranges

A valid value can still use the wrong unit. Store {value, unit} and restrict units by field. Convert only in deterministic code.

Range checks should reflect the domain, not merely the storage type. A temperature, duration, discount, or confidence score needs meaningful bounds. Validate relationships too: subtotal plus tax should reconcile with total within an allowed tolerance; a probability distribution should sum to one under a defined rule.

Avoid “reasonable-looking” repair. If a model returns 250 where the schema expects a fraction from zero to one, do not silently divide by 100. Reject and request a corrected extraction with the source evidence.

Preserve source precision

Reporting more digits than the source implies creates false accuracy. If a document says “about 2.3 million,” the extraction should not become 2,300,000.0000 without a qualifier.

Store the raw span, normalized value, stated unit, and approximation flag. For scientific measurements, include uncertainty or significant figures when provided. Formatting for display should happen after the value’s semantics are fixed.

Test edge cases systematically

Your evaluation set should include:

  • values just above safe-integer boundaries;
  • negative zero and signed amounts;
  • commas used as decimal or thousands separators;
  • very small and very large exponents;
  • currencies with zero, two, and three minor digits;
  • percentages expressed as 8%, 0.08, and 800 basis points;
  • quantities with conflicting units;
  • totals that almost—but do not—reconcile.

Property-based tests can generate magnitudes and scales the hand-written suite misses. Run the same payload through model output parsing, application types, serialization, queues, and database storage.

Observe numeric corrections in production

Log validation failure classes without exposing sensitive values. Track unsafe integers, excess scale, range failures, unit mismatches, and reconciliation errors by prompt release and model policy.

If a repair pass is allowed, record the original payload and whether correction used source evidence. Cap attempts. A repeated mismatch should stop the workflow rather than gradually mutate a financial value.

The takeaway

Structured output guarantees shape only when the schema expresses meaning. Keep identifiers as strings, money in integer minor units or canonical decimals, rates in named representations, and calculations in deterministic code. Validate range, unit, precision, and reconciliation before any side effect. A number that parses is not necessarily a number you can trust.

Share this article

> Want more like this?

Get the best AI insights delivered weekly.

By subscribing, you agree to our Privacy Policy. You can unsubscribe at any time.

> Related Articles

Tags

structured outputsnumeric precisionLLM reliabilitytool callingvalidation

> Stay in the loop

Weekly AI tools & insights.