源本科技 | 码上会

JavaScript Numbers

2026/01/13
18
0

学习目标

  • 理解 JavaScript 中数字的底层存储格式(IEEE 754 双精度浮点数)

  • 掌握科学计数法、不同进制字面量的使用方式

  • 了解浮点数精度问题及其常见解决方案

  • 熟悉 JavaScript 中的类型自动转换规则

  • 掌握常用 Number 对象方法的使用场景


学习内容

JS 中唯一的数字类型

JavaScript 的数字是原始数据类型,与其他语言(如 C++、Java)不同,它不区分整型(int)、浮点型(float)等。所有数字都以 IEEE 754 标准的双精度 64 位二进制格式存储:

  • 第 0–51 位:存储有效数字(尾数部分)

  • 第 52–62 位:存储指数部分

  • 第 63 位:存储符号位(0 为正,1 为负)

这意味着:

  • 整数和小数在内部使用同一套表示方式

  • 安全整数范围为:-(2^53 - 1)2^53 - 1(即 -90071992547409919007199254740991

  • 超出此范围的整数可能丢失精度

let a = 999999999999999;    // 15 位,安全
let b = 9999999999999999;   // 16 位,超出安全范围
console.log(a); // 999999999999999
console.log(b); // 10000000000000000(精度丢失!)

科学计数法

JavaScript 支持用 eE 表示科学计数法,适用于极大或极小的数值:

let large = 156e5;   // 相当于 156 × 10⁵ = 15,600,000
let small = 156e-5;  // 相当于 156 × 10⁻⁵ = 0.00156
console.log(large); // 15600000
console.log(small); // 0.00156

浮点数精度问题

由于二进制无法精确表示某些十进制小数(如 0.1),浮点运算可能存在微小误差

let x = 0.22 + 0.12;
console.log(x); // 0.33999999999999997(非预期结果)

解决方案:缩放法(Scaling)

通过先放大再缩小的方式规避精度问题:

let y = (0.22 * 10 + 0.12 * 10) / 10;
console.log(y); // 0.34(正确结果)

更健壮的做法是使用 Number.EPSILON 或第三方库(如 decimal.js)处理高精度计算。

数字与字符串的加法

JavaScript 的 + 运算符具有双重语义:

  • 两个操作数均为数字 → 执行加法

  • 任一操作数为字符串 → 执行字符串拼接

// 数字相加
let numSum = 10 + 15;
console.log(numSum); // 25

// 字符串拼接
let strConcat = "10" + "30";
console.log(strConcat); // "1030"

// 混合类型:数字转字符串
let mix = 10 + "30";
console.log(mix); // "1030"

数值字符串的自动转换

非加法的算术运算中(如 /, *, -),JavaScript 会自动将字符串转为数字:

let x = "100" / "10"; // 10
let y = "100" * "10"; // 1000
let z = "100" - "10"; // 90
console.log(x, y, z); // 10 1000 90

注意:"100" + "10" 是字符串拼接(结果为 "10010"),而 "100" - "10" 是数值减法(结果为 90)。


字面量的不同进制

JavaScript 支持多种进制的数字字面量:

进制

前缀

示例

十进制值

十进制

33, 3.3

33, 3.3

八进制

0o0(旧式)

0o5620562

370

二进制

0b

0b11

3

十六进制

0x

0xfff

4095

console.log(0o562);   // 370(八进制)
console.log(0b11);    // 3(二进制)
console.log(0xfff);   // 4095(十六进制)

现代 JavaScript 推荐使用 0o 表示八进制(避免与十进制混淆),0 开头的八进制写法已不推荐。


JS 中的类型强制转换

当不同类型的值参与运算时,JavaScript 会自动进行类型转换:

// undefined → NaN
console.log(undefined + 10); // NaN

// null → 0
console.log(null + 5); // 5

// Boolean → Number
console.log(true + 10);  // 11
console.log(false + 10); // 10

// String → Number
console.log(Number("42"));    // 42
console.log(Number("hello")); // NaN

// Symbol 无法转数字
// console.log(Number(Symbol())); // 抛出 TypeError

常用 Number 方法

JavaScript 提供了丰富的 Number 原型方法用于格式化和检测:

let num = 21;

console.log(num.toString());        // "21"
console.log(num.toExponential());   // "2.1e+1"
console.log(num.toPrecision(4));    // "21.00"(保留4位有效数字)
console.log(Number.isInteger(num)); // true
console.log(num.toLocaleString("bn-BD")); // "২১"(孟加拉语数字)

方法

用途

toString(radix)

转为字符串,可指定进制(2~36)

toExponential()

科学计数法表示

toPrecision(n)

返回包含 n 位有效数字的字符串

Number.isInteger()

判断是否为整数

toLocaleString()

按本地化格式输出(如千分位、货币符号等)


补充知识点

  • BigInt:用于表示任意长度的整数(如 123n),与普通 Number 类型不兼容

  • Number 对象 vs 原始值new Number(42) 创建的是对象,应避免使用(性能差且行为异常)

  • 进制转换num.toString(2) 可将数字转为二进制字符串,支持 2~36 进制

console.log((42).toString(2));  // "101010"
console.log((255).toString(16)); // "ff"

重点总结

  • JavaScript 只有一种数字类型:IEEE 754 双精度浮点数

  • 安全整数范围:±(2^53 - 1),超出将丢失精度

  • 浮点运算存在精度问题,可通过缩放法临时解决

  • + 运算符在遇到字符串时执行拼接而非加法

  • 非加法算术运算会自动将字符串转为数字

  • 支持二进制(0b)、八进制(0o)、十六进制(0x)字面量

  • 类型强制转换遵循特定规则(如 null→0, true→1

  • 使用 Number.isInteger() 判断整数,而非 typeof


思考题

  1. 为什么 0.1 + 0.2 !== 0.3 在 JavaScript 中成立?如何安全地比较两个浮点数是否“相等”?

  2. 执行 console.log("5" - "2" + "3")console.log("5" + "2" - "3") 的结果分别是什么?请解释运算顺序和类型转换过程。

  3. 如何将一个十进制数字 255 转换为十六进制字符串 "ff"?如果要转换为大写 "FF" 又该如何实现?