0

I'm trying to better understand why large numbers, with potentially large precisions are inconsistently handled, specifically in JavaScript and it's localization facilities (e.g. ECMA-402/Intl). I'm assuming this has to do with the use of floating point numbers, but I'd like to understand where the limits are and/or how to avoid these pitfalls.

For example, using Intl.NumberFormat:

console.log(new Intl.NumberFormat('en-US', { minimumFractionDigits: 3, maximumFractionDigits: 3 }).format(9999999999990.001)); // logs 9,999,999,999,990.000

let test1 = 9999999999990.001
console.log(test1);  // logs 9999999999990.002

How would I be able to figure out where these numbers start to get inconsistent? Is there some kind of limit? Does that limit change as I increase decimal precision, e.g. :

let test2 = 9999999999990.0004;
console.log(test2) // logs 9999999999990
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
sparty02
  • 566
  • 1
  • 6
  • 13

1 Answers1

1

Is there some kind of limit? Does that limit change as I increase decimal precision?

Yes, and yes. Floating-point numbers in JavaScript are themselves stored in 64 bits of space, which means they are limited in the precision they can represent. See this answer for more information.

How would I be able to figure out where these numbers start to get inconsistent?

Pass your "numeric literals" to a function in the form of strings, and check to see if that string, when coerced to a number and back, returns the correct literal:

function safeNumber (s) {
  if (String(+s) !== s)
    throw new Error('Unsafe number!')
  return +s
}

let safe = safeNumber('999999999999999')
console.log(safe)

let unsafe = safeNumber('9999999999990.001')
console.log(unsafe)
Community
  • 1
  • 1
gyre
  • 16,369
  • 3
  • 37
  • 47
  • This is great and informative, but what I'm really trying to do is understand, ahead of time, where these "unsafe" numbers are. If I use Intl formatting to format a currency, I need to know, at which point, my values won't reflect their "true" value. In other words, what fits in 64 bits of space (limits before the decimal and limits after the decimla).... unless I'm understanding it wrong! – sparty02 Mar 31 '17 at 19:42
  • 15 significant digits. See http://stackoverflow.com/questions/1379934/large-numbers-erroneously-rounded-in-javascript/1380058#1380058. – gyre Mar 31 '17 at 20:05