The huge, the tiny, and the (sometimes) ugly:
Javascript Numbers

Murray Bourne
BrisJS :: 4 Aug 2025

The motivation (1)

  • Sketch the graph of y = f(x)
  • x012345678910
    y

The motivation (2)

The motivation (3)

  • We want to animate graphs efficiently
  • We want to minimise data points, calculations
  • We want to "plot to infinity"
  • Improved versions: ASVG

Function:

  • ixtan(x)
  • m =
  • d =

Stumbling blocks (1)

  • expressionJS output

Stumbling blocks (2)

  • Max. significant digits in JS numbers:
  • 17, because:
  • IEEE 754 double-precision binary floating-point format: binary64
  • Largest safe integer:
  • = 253 − 1 = 9,007,199,254,740,991
  • Largest possible number:
  • = (253 − 1)*2971 ≈ 1.7976931348623157e308

Big integers

  • 20-digit number: use BigInt (introduced 2020)
  • expressionJS output

Large numbers summary (+ve)

0 Number.MAX_SAFE_INTEGER (≈9e15) "safe" integers Number.MAX_VALUE (≈1.8e308) BigInt Infinity
  • Number.MAX_SAFE_INTEGER (253 − 1 ≈ 9e15) is the largest "safe" integer
  • (positive)
  • Number.MAX_VALUE (≈1.8e308) is the largest possible distinct number
  • BigInt is for integers that are larger than the Number primitive can handle. Uses suffix "n", e.g. 123456789012345678901n
  • Infinity is larger than any other number in Javascript

Small numbers

  • Beware the "Sometimes works, sometimes not" cases...

Adding decimals (1)

Adding decimals (2)

  • How about x == 0.4?

Adding decimals (PHP)

  • Using PHP:
  • <?php  for($x=0; $x<1.5; $x += 0.2) {
      echo "x = $x \n";
      if($x == 0.6) {
        break;
      }
    } ?>
  • x = 0
    x = 0.2
    x = 0.4
    x = 0.6
    x = 0.8
    x = 1
    x = 1.2
    x = 1.4
  • (Displays the floats OK, but misses the equality test)

Small numbers

  • Smallest positive number:
  • Number.MIN_VALUE = 2−1074 = 5e-324
  • Somewhat useless(?), as:
  • 5 + Number.MIN_VALUE = 5
  • In fact:
  • 5 + 9e307 * Number.MIN_VALUE = 5.000000000000001

More useful: EPSILON (ε)

  • Number.EPSILON = 2−52 ≈ 2.22e-16
  • Reason: 52 bits to represent the mantissa
  • Represents the smallest representable number near 1
  • 1 + Number.EPSILON = 1.0000000000000002
  • But:
  • 5 + Number.EPSILON = 5
  • Reason: Exponent is bigger, so accuracy lower

Number.EPSILON

  • Solution:
  • Multiply by the number you're comparing:
  • 5 + 5 * Number.EPSILON = 5.000000000000001
  • Use as:
  • let x = 200.1, y = 200.2, z = 400.3;
  • x + y == z   // output: false
  • if( Math.abs(x + y - z) < 400 * Number.EPSILON) {
      console.log("yeah");
    } else {
      console.log("nah")
    } 
  • // output: yeah (equal)

Small numbers summary (+ve)

0 1 2 Number.MIN_VALUE 1 + ε 1.0000000000000002 2 + 2ε 2.0000000000000004
  • Number.MIN_VALUE (2−1074 − 1 = 5e-324) is the smallest possible positive number (useless)
  • Number.EPSILON = 2−52 ≈ 2.22e-16 indicates accuracy of 1
  • 2 + 2*Number.EPSILON for numbers near 2

Calculating π using BigInt (1)

Calculating π using BigInt (2)

  • This uses:
    1. BigInt
    2. A spigot algorithm, based on Johann Lambert's continued fraction expression for π (pub. 1770):
  • $$\pi = \frac{4}{1+\frac{1^2}{3+\frac{2^2}{5+\frac{3^2}{7+\dots}}}}$$

Overall summary

Stuff I learned:

  • Be sceptical of Javascript numerical output
  • Javascript numbers don't always follow actual mathematical principles
  • Beware the "it mostly works" trap
  • Throwing more data points at a problem is not always the best solution for accuracy or usability ^_^

Quiz

  • QuesexpressionJS output
    T or F?
    T or F?
    Value?
    Value?
    Value?
    Value?
    Value?
    Value?
    Output?

The end

Thank you!

@bourne2learn