3 Numbers
JavaScript treats numbers with more complexity than they first appear to have: the language mainly offers Number and BigInt, but the familiar Number type is actually a 64-bit IEEE 754 floating-point value. This explains the famous 0.1 + 0.2 surprise, because many decimal fractions cannot be represented exactly in binary, so they are rounded before arithmetic even begins. The chapter shows how numbers are encoded as bits, how binary and 2’s complement represent whole numbers, and why floating-point exists to handle fractions, very large values, infinities, and other edge cases.
The discussion then breaks down the structure of double-precision values into sign, exponent, and significand, showing how the exponent shifts the binary point and how the significand stores precision. It explains that this design gives JavaScript a huge numeric range, but only limited exact precision, so comparisons often need tolerance rather than strict equality. Number.EPSILON is presented as a practical tool for checking whether floating-point values are close enough, while the chapter also highlights the limits of this system, including special values like NaN and the maximum safe integer beyond which exact whole-number representation is no longer guaranteed.
To handle exact large integers, BigInt is introduced as a separate type that grows as needed instead of relying on fixed-width floating-point storage. The text explains how BigInts are created, how they are stored internally in chunks, and why they cannot be mixed freely with Numbers in arithmetic. It then looks ahead to Decimal, a proposed exact base-10 type aimed at financial and other decimal-heavy calculations, and closes by describing how V8 optimizes common number usage with SMIs for small integers and HeapNumbers for everything else, along with practical advice to keep code fast by using integers where possible, avoiding mixed numeric types, and choosing the right representation for the job.
Unsigned and signed binary layout consists of any number of bits. In the unsigned variant, every bit is used to represent the value, whereas in the signed variant, the most significant bit is reserved as representing the sign and the remaining bits represent the value.
The “double-precision” floating point layout divides the 64 available bits into distinct components, including a sign-bit, eleven exponent bits, and 52 bits for the significand.
Summary
- Numbers are 64-bit floating-point values (Binary64) that cannot precisely represent decimal fractions like 0.1 or 0.2.
- Binary encoding causes 0.1 + 0.2 to equal 0.30000000000000004 due to infinite repeating patterns in base-2 representation.
- 2's complement encoding enables signed integers by inverting bits and adding 1, allowing the same arithmetic circuits for positive and negative numbers.
- Floating-point trades range for precision: 53 bits of accuracy regardless of magnitude, from 5e-324 to 1.7976931348623157e+308.
- The maximum safe integer is 2^53 - 1 (9,007,199,254,740,991), beyond which not all integers can be represented exactly.
- Number.EPSILON provides the smallest representable difference for comparing floating-point values that should be equal but aren't due to rounding.
- BigInt uses dynamic memory allocation to represent arbitrarily large integers without precision loss, at 10-200x performance cost.
- JavaScript forbids mixing BigInt and Number in arithmetic to prevent accidental precision loss, though comparisons work.
- The proposed Decimal type will use base-10 encoding to enable exact decimal arithmetic for financial and scientific calculations.
- V8 optimizes integers between -2^31 and 2^31-1 as SMIs, storing them directly without heap allocation for better performance.
- Consistent numeric types in arrays and loops help V8 maintain optimizations, while mixing types forces slower generic handling.
FAQ
Why does 0.1 + 0.2 not equal 0.3 in JavaScript?
JavaScript uses IEEE 754 double-precision floating-point numbers, so values like 0.1 and 0.2 cannot be represented exactly in binary. Tiny rounding errors accumulate, producing 0.30000000000000004 instead of 0.3.What is the difference between Number and BigInt?
Number is a 64-bit floating-point type used for general numeric work, while BigInt stores arbitrarily large integers exactly. Use BigInt when integers exceed the safe range of Number.What is the maximum safe integer in JavaScript?
The maximum safe integer is9007199254740991 (2^53 - 1). Beyond this value, JavaScript Number values may stop representing every integer exactly.How does 2’s complement represent negative integers?
In 2’s complement, the most significant bit indicates the sign, and negative numbers are encoded by inverting the bits of the positive value and adding 1. This makes binary arithmetic work naturally for signed integers.What is endianness and why does it matter?
Endianness is the byte order used to store multi-byte numbers. Big-endian stores the most significant byte first, while little-endian stores the least significant byte first. It matters when exchanging binary data between systems.What are the parts of a Binary64 floating-point number?
A Binary64 value has 64 bits: 1 sign bit, 11 exponent bits, and 52 significand bits. The significand also uses an implicit leading 1 for normalized numbers, giving about 53 bits of precision.How can Number.EPSILON help compare floating-point values?
Number.EPSILON is the smallest difference between two representable Binary64 numbers near 1. It can be used to check whether two values are close enough to be considered equal, especially when scaled for larger magnitudes.Why can’t JavaScript mix Number and BigInt in arithmetic?
JavaScript forbids mixingNumber and BigInt in arithmetic to avoid accidental precision loss. You must explicitly convert one type to the other before doing math.What is the proposed Decimal type in JavaScript?
The proposedDecimal type aims to provide exact decimal arithmetic using a base-10 representation. It is meant for cases like finance where values such as 0.1 + 0.2 should produce an exact decimal result.
JavaScript in Depth ebook for free