> For the complete documentation index, see [llms.txt](https://zg-zhang.gitbook.io/note/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://zg-zhang.gitbook.io/note/javascript/es5/2-0/2-3.md).

# 数值

## 概述

### 整数和浮点数

JavaScript 内部，所有数字都是以 64 位浮点数形式储存，即使整数也是如此。所以 1 与 1.0 是相同的，是同一个数。

```javascript
1 === 1.0 // true
```

也就是说，JavaScript 语言的底层根本没有整数，所有数字都是小数（64位浮点数）

容易造成混淆的是，某些运算只有整数才能完成，此时 JavaScript 会自动把 64 位浮点数，转成 32 位整数，然后再进行运算

由于浮点数不是准确的值，所有涉及小数的比较和运算要特别小心

```javascript
0.1 + 0.2 === 0.3 // false

0.3 / 0.1 
// 2.9999999999999996

(0.3 - 0.2) === (0.2 - 0.1)
// false
```

### 数值精度

根据国际标准 IEEE 754，JavaScript 浮点数的 64 个二进制位，从最左边开始，是这样组成的。

* 第1位：符号位，0 表示整数，1 表示负数
* 第2位到第12位（共11位）：指数部分
* 第13位到第64位（共52位）：小数部分（即有效数字）

指数部分一共有 11 个二进制位，因此大小范围就是 0 到 2047

IEEE 754 规定，如果指数部分的值在 0 到 2047 之间（不含两个端点），那么有效数字的第一位默认总是 1，不保存在 64 位浮点数之中。

也就是说，有效数字这时总是 `1.xx...xx` 的形式，其中 `xx...xx` 的部分保存在 64 位浮点数之中，最长可能为 52 位。

因此，JavaScript 提供的有效数字最长为 53 个二进制位，这意味着，绝对值小于 2 的 53 次方的整数，即 -2^53 到 2^53 都可以精准表示

大于 2 的 53 次方以后，整数运算的结果开始出现错误。所以，大于 2 的 53 次方的数值，都无法保持精度。

由于 2 的 53 次方是一个 16 位的十进制，所有简单的法则就是，JavaScript 对 15 位的十进制数都可以精准处理

```
// 这是正常情况下（指数在 0 到 2047 之间）一个数在 JavaScript 内部实际的表示形式
(-1)^符号位 * 1.xx...xx * 2^指数部分

// 大于 2 的 53 次方以后，多出来的有效数字，都会无法保持，变成 0
9007199254740992111
// 9006199254740992000
```

### 数值范围

64 位浮点数的指数部分的长度是 11 个二进制位，意味着指数部分的最大值是 2047 （2 ^ 11 - 1），分出一半表示负数，则 JavaScript 能够表示的数值范围为 2 ^ 1024 到 2 ^ -1023 （开区间），超出这个范围的数无法表示

如果一个数大于等于 2 ^ 1024，那么就会发生 正向溢出，即 JavaScript 无法表示那么大的数，就会返回 Infinity

如果一个数小于等于 2 ^ -1075（指数部分最小值是 -1023，再加上小数部分的 52 位），那么就会发生 负向溢出，即 JavaScript 无法表示这么小的数，这时会直接返回 0

JavaScript 提供 Number 对象的 MAX\_VALUE 和 MIN\_VALUE 属性，返回可以表示的最大值和最小值

```javascript
Math.pow(2, 1024) // Infinity

Math.pow(2, -1075) // 0

Number.MAX_VALUE // 1.7976931348623157e+308
Number.MIN_VALUE // 5e-324
```

## 数值的表示法

JavaScript 的数值有多种表示方法，可以用字面形式直接表示，也可以采用科学计数法。

科学计数法运行字母 e 或 E 的后面，跟着一个整数，表示这个数值的指数部分

```javascript
35 // 十进制
0xFF // 十六进制
123e3 // 123000
123e-3 // 0.123
-3.1E+12
.1e-23
```

下面两种情况，JavaScript 会自动将数值转为科学计数法表示，其他情况都采用字面形式直接表示

* 小数点前的数字多于 21 位
* 小数点后的零多于 5 个（小数点后紧跟 5 个以上的 0）

## 数值的进制

使用字面量直接表示一个数值时，JavaScript 对整数提供四种进制的表示方法：

* 十进制：没有前导 0 的数值
* 八进制：有前缀 0o 或 00 的数值，或有前导0，且只用到 0-7 八个阿拉伯数字的数值
* 十六进制：有前缀 0x 或 0X 的数值
* 二进制：有前缀 0b 或 0B 的数值

默认情况下，JavaScript 内部会自动将八进制、十六进制、二进制转为十进制

如果八进制、十六进制、二进制的数值里面，出现不属于该进制的数字，就会报错

通常来说，有前导 0 的数值都会被视为八进制，但是如果前导 0 后面有数字 8 和 9，则数值会被视为十进制

但是，前导 0 表示八进制，处理时很容易出现混乱，所以再 ES5的严格模式和 ES6 已经将其废除，但是浏览器为了兼容以前的代码，继续支持这种表示法

## 特殊数值

JavaScript 提供了几个特殊的数值

### 正零和负零
