JSON transfer of bigint: 12000000000002539 is converted to 12000000000002540?

The value is actually not exceeding the maximum numeric value in JavaScript (which is “only” 1.7308 or so).

However, the value is exceeding the range of “integral precision”. It is not that the wrong number is sent: rather, it is that the literal 12000000000002539 can only be represented as precisely as 12000000000002540, and thus there was never the correct numeric value in JavaScript. (The range of integrals is about +/- 253.)

This is an interesting phenomena of using a double relative-precision (binary64 in IEEE-754 speak) type to store all numeric values, including integers:

12000000000002539 === 12000000000002540 // true

The maximum significant number of decimal digits that be precisely stored as a numeric value is 15 (15.95, really). In the above, there are 17 significant digits, so some of the least-significant information is silently lost. In this case, as the JavaScript parser/engine reads in the literal value.

The only safe way to handle integral numbers of this magnitude in JavaScript is to use a string literal or to break it down in another fashion (e.g. a custom numeric type or a “bigint library”). However, I recommend just using a string, as it is human readable, relatively compact (only two extra characters in JSON), and doesn’t require special serialization. Since the value is just an “id” in this case, I hope that math does not need to be performed upon it šŸ™‚

Happy coding.

Leave a Comment