Skip to content

fix(schema): use big.js to avoid floating-point errors in multipleOf#259

Open
spiderocious wants to merge 1 commit into
remoteoss:mainfrom
spiderocious:fix/222-multipleof-precision
Open

fix(schema): use big.js to avoid floating-point errors in multipleOf#259
spiderocious wants to merge 1 commit into
remoteoss:mainfrom
spiderocious:fix/222-multipleof-precision

Conversation

@spiderocious

@spiderocious spiderocious commented May 29, 2026

Copy link
Copy Markdown

Summary

Fixes multipleOf validation incorrectly rejecting valid numbers due to floating-point rounding errors. For example, 100 with multipleOf: 0.01 was reported as invalid because 100 % 0.01 evaluates to 0.0099... rather than 0 in plain JavaScript arithmetic.

As suggested by @lukad in the issue, this replaces the native modulo check with arbitrary-precision arithmetic via big.js, which eliminates this class of rounding error entirely. big.js adds ~3KB
(minified + gzipped) and has zero dependencies.

Changes Made

  • src/validation/number.ts

    • Replaced the naive value % multipleOf !== 0 check with an isMultipleOf helper that uses big.js for the modulo operation.
    • The helper guards against the RangeError big.js throws when an operation exceeds its precision limit (e.g. 1e308 divided by a tiny multipleOf); in that case the value is treated as not a multiple, matching the expected invalid result instead of throwing.
  • test/json-schema-test-suite/failed-json-schema-test-suite.json

    • Re-enabled two official JSON Schema Test Suite cases that were previously ignored because of this bug: "0.0075 is multiple of 0.0001" and "any integer is a multiple of 1e-8". They now pass.
  • test/validation/number.test.ts

    • Added a unit test covering floating-point cases (incl. the issue's 100 / 0.01 example) and a negative case (0.00751 is not a multiple of 0.0001) to confirm genuine non-multiples still fail.
  • package.json

    • Added big.js (dependency) and @types/big.js (devDependency).

Related Issues/PRs

Fixes #222

Screenshots (Before/After if applicable)

N/A — validation-only change.

Checklist


Note

Low Risk
Localized change to number multipleOf validation with a small dependency; min/max and other number rules are unchanged.

Overview
multipleOf validation no longer uses JavaScript’s % operator, which falsely rejects valid values when divisors are fractional (e.g. 100 with multipleOf: 0.01).

The check now uses big.js via a new isMultipleOf helper that tests remainder with arbitrary-precision mod. If big.js throws RangeError on extreme magnitudes, the value is treated as not a multiple instead of crashing validation.

big.js and @types/big.js were added as dependencies. Two JSON Schema Test Suite cases that were previously allow-listed as failures were removed from the ignore list, and unit tests cover decimal multipleOf pass/fail cases.

Reviewed by Cursor Bugbot for commit dac879e. Bugbot is set up for automated code reviews on this repo. Configure here.

@spiderocious spiderocious marked this pull request as ready for review June 2, 2026 16:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

multipleOf doesn't account for rounding errors

1 participant