JavaScript: Numbers & Math

Understand number systems, floating-point precision, every Number method, the Math object, and BigInt for large integers.

Number Systems

JavaScript lets you write numeric literals in four bases: decimal (base 10), binary (base 2), octal (base 8), and hexadecimal (base 16). All are stored internally as the same IEEE 754 double-precision float.

Numeric Literal Bases

Different prefixes signal which base a literal is written in.

  • Decimal: no prefix, 255
  • Binary: 0b prefix, 0b11111111 → 255
  • Octal: 0o prefix, 0o377 → 255
  • Hexadecimal: 0x prefix, 0xFF → 255
  • Use num.toString(base) to convert a number to any base string

Four Numeric Bases

All four literals equal 255: base is just a notation, not a different value.

Floating Point Precision Issues

JavaScript uses IEEE 754 double-precision floating-point, which cannot represent some decimal fractions exactly in binary. This causes the infamous 0.1 + 0.2 !== 0.3 bug that surprises every new developer.

IEEE 754 Precision

Floating-point arithmetic is approximate: never use === to compare float results.

  • 0.1 + 0.2 evaluates to 0.30000000000000004, not exactly 0.3
  • Fix for display: (0.1 + 0.2).toFixed(2)"0.30"
  • Fix for comparison: compare within a tolerance, Math.abs(a - b) < 1e-10
  • For money: store values as integers (cents) and divide for display
  • Number.MAX_SAFE_INTEGER = 253 − 1 = 9007199254740991

Floating Point Precision

Three strategies: toFixed for display, epsilon for comparison, integers for money.

toFixed() and toPrecision()

Both methods format a number as a string. toFixed(n) controls decimal places; toPrecision(n) controls total significant digits.

toFixed() / toPrecision()

Both return strings: wrap in Number() if you need a numeric result.

  • toFixed(n): rounds to n decimal places, (3.14159).toFixed(2)"3.14"
  • toPrecision(n): n significant digits total, (123.456).toPrecision(4)"123.5"
  • Both return strings: use Number() or + to convert back
  • toFixed is the standard choice for displaying currency

toFixed and toPrecision

toFixed(2) is the standard for prices and percentages: remember it returns a string.

parseInt() and parseFloat()

These global functions parse a string and extract the leading numeric portion, ignoring any trailing non-numeric characters. This makes them ideal for reading values from the DOM or CSS.

parseInt() / parseFloat()

Parse a numeric value from the start of a string: stops at the first non-numeric character.

  • parseInt("42px")42, ignores trailing "px"
  • parseFloat("3.14em")3.14
  • Returns NaN if the string does not start with a number
  • parseInt(str, radix): always pass the radix (10) to avoid octal surprises

parseInt and parseFloat

Always pass 10 as the radix to parseInt: omitting it can misparse strings like '010'.

isNaN(), isFinite(), and Number.isInteger()

These methods check numeric validity. Always prefer the Number. static versions over the global functions: they do not coerce their argument first.

Numeric Validation Methods

Use Number.isNaN() and Number.isFinite(): the global versions coerce strings and can mislead.

  • Number.isNaN(v): true only if v is actually NaN (no coercion)
  • isNaN("abc"): true because "abc" coerces to NaN, can be misleading
  • Number.isFinite(v): true if v is a finite number (not Infinity or NaN)
  • Number.isInteger(v): true if v is a whole number with no decimal part

isNaN, isFinite, isInteger

Number.isNaN('abc') is false: the string is not NaN. The global isNaN coerces first, causing false positives.

Math.round(), Math.ceil(), and Math.floor()

These three methods round a floating-point number to an integer. They differ in the direction of rounding.

Rounding Methods

Three rounding directions: nearest, always up, always down.

  • Math.round(n): rounds to nearest integer (0.5 rounds up)
  • Math.ceil(n): always rounds up (ceiling)
  • Math.floor(n): always rounds down (floor)
  • To round to n decimal places: Math.round(n * 100) / 100

round, ceil, floor

ceil always goes up, floor always goes down: round goes to the nearest.

Math.max() and Math.min()

Math.max() returns the largest of the provided values; Math.min() returns the smallest. Use spread to apply them to an array.

Math.max() / Math.min()

Accept any number of arguments: use spread (...) to pass an array.

  • Math.max(1, 5, 3)5
  • Math.min(1, 5, 3)1
  • With an array: Math.max(...nums)
  • Math.max() with no arguments returns -Infinity

Math.max and Math.min

The clamp pattern (Math.min + Math.max) is a common real-world use case.

Math.random()

Math.random() returns a pseudo-random float between 0 (inclusive) and 1 (exclusive). Scale and floor it to get integers in any range.

Math.random()

Returns [0, 1): multiply and floor to get integers in a custom range.

  • Range [0, 1): 0 is possible, 1 is never returned
  • Random integer 0–9: Math.floor(Math.random() * 10)
  • Random integer min–max (inclusive): Math.floor(Math.random() * (max - min + 1)) + min
  • Not cryptographically secure: use crypto.getRandomValues() for security-sensitive use

Math.random()

randInt(min, max) is the utility function every JS developer memorises.

Math.pow() and Math.sqrt()

Math.pow(base, exp) raises a number to a power. Math.sqrt(n) returns the square root. The ** operator is now preferred over Math.pow().

Math.pow() / Math.sqrt()

Power and square root: use ** operator instead of Math.pow in modern code.

  • Math.pow(2, 8)256, same as 2 ** 8
  • Math.sqrt(144)12
  • Math.sqrt of a negative returns NaN
  • Cube root: Math.cbrt(27)3

pow and sqrt

Pythagorean theorem in one line: a real-world use of sqrt.

Math.abs()

Math.abs(n) returns the absolute (non-negative) value of a number. It is commonly used to calculate distances and differences regardless of direction.

Math.abs()

Strips the sign: useful for distances, differences, and tolerances.

  • Math.abs(-42)42
  • Math.abs(42)42, positive stays positive
  • Use to compare two numbers regardless of order: Math.abs(a - b)

Math.abs()

Math.abs(a - b) gives the distance between two numbers regardless of which is larger.

Math Constants

The Math object exposes several built-in numeric constants. The most important are Math.PI and Math.E.

Math Constants

Built-in constants: always use these instead of hardcoding approximations.

  • Math.PI: π ≈ 3.141592653589793
  • Math.E: Euler's number ≈ 2.718281828459045
  • Math.LN2: natural log of 2 ≈ 0.693
  • Math.SQRT2: √2 ≈ 1.414
  • Number.EPSILON: smallest difference between two floats (~2.22e-16)
  • Number.MAX_SAFE_INTEGER: 9007199254740991

Math Constants in Use

Math.PI * r²: the circle area formula, readable and precise.

BigInt for Large Numbers

Regular JavaScript numbers lose precision above Number.MAX_SAFE_INTEGER. BigInt handles arbitrarily large integers exactly, at the cost of not being mixable with regular numbers.

BigInt

Arbitrarily precise integers: suffix n to a literal or wrap with BigInt().

  • Append n: 9007199254740993n
  • Cannot mix with number in arithmetic: convert explicitly first
  • Supports all arithmetic operators: +, -, *, /, %, **
  • Division truncates (no floats): 7n / 2n === 3n
  • Use for database IDs, cryptography, or any integer beyond 253−1

BigInt vs Number Precision

BigInt division truncates toward zero: 7n / 2n is 3n, not 3.5.

Knowledge Check

1. What prefix denotes a hexadecimal literal in JavaScript?

2. What is the result of 0.1 + 0.2 === 0.3 in JavaScript?

3. What does (3.14159).toFixed(2) return?

4. What does parseInt("42px") return?

5. Which method correctly checks if a value is NaN?

6. What does Math.floor(4.9) return?

7. How do you generate a random integer between 0 and 9 (inclusive)?

8. What is Math.sqrt(144)?

9. What is the value of Math.PI rounded to 5 decimal places?

10. Why can BigInt not be mixed with regular numbers in arithmetic?