3 Numbers
This chapter covers
- Exploring why 0.1 + 0.2 doesn't equal 0.3 in floating-point
- Encoding integers with binary and 2's complement
- Comparing floating-point values safely with Number.EPSILON
- Working with BigInt beyond the safe integer limit
- Previewing the proposed Decimal type for exact decimals
- Examining V8's SMI optimization for integer performance
In Chapter 2, we discovered that strings, despite seeming simple, hide surprising complexity in their encoding and implementation. Numbers in JavaScript present an equally deceptive simplicity. While most programming languages make you choose between integers and decimals, signed and unsigned, 8-bit and 64-bit, JavaScript offers just two numeric types: Number and BigInt.
Consider this seemingly basic arithmetic:
console.log(0.1 + 0.2); // 0.30000000000000004 console.log(0.3); // 0.3 console.log(0.1 + 0.2 === 0.3); // false
This result bewilders newcomers and has spawned countless memes, but it's not a bug. It's a direct consequence of how JavaScript chose to represent all numbers as double-precision floating-point values. This single decision shapes everything from why your financial calculations might be off by a penny, to why counting past 9,007,199,254,740,991 becomes unreliable, to why V8 secretly treats small integers completely differently than decimals.