Skip to content

fix: use BigInt for large integers to preserve precision#28

Open
remorses wants to merge 4 commits intolukeed:masterfrom
remorses:fix/large-number-precision
Open

fix: use BigInt for large integers to preserve precision#28
remorses wants to merge 4 commits intolukeed:masterfrom
remorses:fix/large-number-precision

Conversation

@remorses
Copy link
Copy Markdown

@remorses remorses commented Jan 23, 2026

Fixes #29

Numbers larger than Number.MAX_SAFE_INTEGER (2^53-1) lose precision when converted to JavaScript Number.

// Before: precision lost
mri(['--id', '9007199254740993'])
// { id: 9007199254740992 }

// After: BigInt preserves precision  
mri(['--id', '9007199254740993'])
// { id: 9007199254740993n }

This affects downstream packages like cac which uses mri for argument parsing.

Behavior:

  • Safe integers (≤ 9007199254740991) → number
  • Large integers (> MAX_SAFE_INTEGER) → bigint
  • Floats, scientific notation, leading zeros → number (unchanged)

Tests added:

  • Large integers use BigInt
  • MAX_SAFE_INTEGER boundary
  • MIN_SAFE_INTEGER boundary
  • Large negative integers
  • Leading zeros remain numbers

cc @lukeed

Numbers larger than Number.MAX_SAFE_INTEGER lose precision when
converted to JavaScript Number. This change detects integer strings
that would lose precision and returns BigInt instead.

- 9007199254740991 (MAX_SAFE_INTEGER) -> Number
- 9007199254740993 -> BigInt (would lose precision as Number)
- 1e7, 3.14, etc -> Number (floats unchanged)
Copilot AI review requested due to automatic review settings January 23, 2026 14:20
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes precision loss for large integers in command-line argument parsing by automatically using BigInt for integer strings that exceed JavaScript's safe integer range (2^53-1). The implementation adds a new toNum function that detects when numeric conversion would lose precision and uses BigInt instead.

Changes:

  • Added toNum function to detect and preserve precision for large integers using BigInt
  • Refactored numeric conversion logic in toVal to use the new toNum function
  • Added comprehensive tests for BigInt boundary conditions and negative large integers

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.

File Description
src/index.js Implements new toNum function with BigInt support for precision-loss detection and integrates it into the value conversion logic
test/num.js Adds three test cases covering large integer BigInt conversion, MAX_SAFE_INTEGER boundary behavior, and large negative integers

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/index.js Outdated
Comment thread test/num.js Outdated
Comment thread test/num.js Outdated
- Fix leading zeros incorrectly becoming BigInt
- Add MIN_SAFE_INTEGER boundary test
- Add leading zeros test
@lukeed
Copy link
Copy Markdown
Owner

lukeed commented Jan 23, 2026

This is technically a breaking change, as bigints werent supported in Node until 10.x and this lib is still 4+
And I was considering dropping number-parsing altogether in the next major.

While this PR is technically correct, I wonder how frequent it's being bumped into

Thoughts?

@remorses
Copy link
Copy Markdown
Author

I can update the PR to return a number if BigInt constructor is missing. I don't think making a breaking change for this issue is worth it. Number parsing is a fine in my opinion

- Check typeof BigInt !== 'undefined' before using BigInt()
- Move BigInt tests to _bigint.js (not matched by tape glob)
- Conditionally require BigInt tests when available
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.

Large integers lose precision when parsed

3 participants