## 15.数字
> 原文: [http://exploringjs.com/impatient-js/ch_numbers.html](http://exploringjs.com/impatient-js/ch_numbers.html)
>
> 贡献者:[飞龙](https://github.com/wizardforcel)
本章介绍 JavaScript 的单一类型数字,`number`。
### 15.1。 JavaScript 只有浮点数
您可以在 JavaScript 中表示整数和浮点数:
```js
98
123.45
```
但是,所有数字只有一种类型:它们都是*双精度*,根据 IEEE 浮点运算标准(IEEE 754)实现的 64 位浮点数。
整数只是没有小数部分的浮点数:
```js
> 98 === 98.0
true
```
请注意,在大多数情况下,大多数 JavaScript 引擎通常都能够使用实际整数,并具有所有相关的性能和存储大小优势。
### 15.2。数字字面值
让我们检查数字的字面值。
#### 15.2.1。整数字面值
几个*整数字面值*让你用各种基数表示整数:
```js
// Binary (base 2)
assert.equal(0b11, 3);
// Octal (base 8)
assert.equal(0o10, 8);
// Decimal (base 10):
assert.equal(35, 35);
// Hexadecimal (base 16)
assert.equal(0xE7, 231);
```
#### 15.2.2。浮点字面值
浮点数只能用基数 10 表示。
分数:
```js
> 35.0
35
```
指数:`eN`表示`10 ** N`
```js
> 3e2
300
> 3e-2
0.03
> 0.3e2
30
```
#### 15.2.3。语法缺陷:整数字面值的属性
访问整数字面值的属性会带来陷阱:如果整数字面值后面紧跟一个点,则该点被解释为小数点:
```js
7.toString(); // syntax error
```
有四种方法可以解决这个陷阱:
```js
7.0.toString()
(7).toString()
7..toString()
7 .toString() // space before dot
```
### 15.3。数字运算符
#### 15.3.1。二元算术运算符
```js
assert.equal(1 + 4, 5); // addition
assert.equal(6 - 3, 3); // subtraction
assert.equal(2 * 1.25, 2.5); // multiplication
assert.equal(6 / 4, 1.5); // division
assert.equal(6 % 4, 2); // remainder
assert.equal(2 ** 3, 8); // exponentiation
```
`%`是余数运算符(不是模运算符) - 其结果具有第一个操作数的符号:
```js
> 3 % 2
1
> -3 % 2
-1
```
#### 15.3.2。一元加法和相反数
```js
assert.equal(+(-3), -3); // unary plus
assert.equal(-(-3), 3); // unary negation
```
两个运算符都将他们的操作数强制转换为数字:
```js
> +'7'
7
> +'-12'
-12
> -'9'
-9
```
#### 15.3.3。自增(`++`)和自减(`--`)
自增运算符`++`存在前缀版本和后缀版本。在这两个版本中,它破坏性地将其操作数加一。因此,其操作数必须是可以更改的存储位置。自减运算符`--`的工作方式相同,但从其操作数中减一。接下来的两个示例解释了前缀和后缀版本之间的区别。
前缀`++`和前缀`--`:更改然后返回。
```js
let foo = 3;
assert.equal(++foo, 4);
assert.equal(foo, 4);
let bar = 3;
assert.equal(--bar, 2);
assert.equal(bar, 2);
```
后缀`++`和后缀`--`:返回然后更改。
```js
let foo = 3;
assert.equal(foo++, 3);
assert.equal(foo, 4);
let bar = 3;
assert.equal(bar--, 3);
assert.equal(bar, 2);
```
##### 15.3.3.1。操作数:不仅仅是变量
您还可以将这些运算符应用于属性值:
```js
const obj = { a: 1 };
++obj.a;
assert.equal(obj.a, 2);
```
并且用于数组元素:
```js
const arr = [ 4 ];
arr[0]++;
assert.deepEqual(arr, [5]);
```
![](https://img.kancloud.cn/3e/d5/3ed5755d562179ae6c199264f5e21157.svg) **练习:数字运算符**
`exercises/numbers-math/is_odd_test.js`
### 15.4。转换为数字
这些是将值转换为数字的三种方法:
* `Number(value)`
* `+value`
* `parseFloat(value)`(避免;与其他两个不同!)
建议:使用描述性`Number()`。
例子:
```js
assert.equal(Number(undefined), NaN);
assert.equal(Number(null), 0);
assert.equal(Number(false), 0);
assert.equal(Number(true), 1);
assert.equal(Number(123), 123);
assert.equal(Number(''), 0);
assert.equal(Number('123'), 123);
assert.equal(Number('xyz'), NaN);
```
可以配置如何将对象转换为数字。例如,通过覆盖`.valueOf()`:
```js
> Number({ valueOf() { return 123 } })
123
```
![](https://img.kancloud.cn/3e/d5/3ed5755d562179ae6c199264f5e21157.svg) **练习:转换为数字**
`exercises/numbers-math/parse_number_test.js`
### 15.5。错误值
发生错误时返回两个数字值:
* `NaN`
* `Infinity`
### 15.6。错误值:`NaN`
`NaN`是“非数字”的缩写。具有讽刺意味的是,JavaScript 认为它是一个数字:
```js
> typeof NaN
'number'
```
什么时候返回`NaN`?
如果无法解析数字,则返回`NaN`:
```js
> Number('$$$')
NaN
> Number(undefined)
NaN
```
如果无法执行操作,则返回`NaN`:
```js
> Math.log(-1)
NaN
> Math.sqrt(-1)
NaN
```
如果操作数或参数是`NaN`(传播错误),则返回`NaN`:
```js
> NaN - 3
NaN
> 7 ** NaN
NaN
```
#### 15.6.1。检查`NaN`
`NaN`是唯一不严格等于自己的 JavaScript 值:
```js
const n = NaN;
assert.equal(n === n, false);
```
这些是检查值`x`是否为`NaN`的几种方法:
```js
const x = NaN;
assert.equal(Number.isNaN(x), true); // preferred
assert.equal(Object.is(x, NaN), true);
assert.equal(x !== x, true);
```
在最后一行,我们使用比较小技巧来检测`NaN`。
#### 15.6.2。在数组中查找`NaN`
有些数组方法找不到`NaN`:
```js
> [NaN].indexOf(NaN)
-1
```
其他可以:
```js
> [NaN].includes(NaN)
true
> [NaN].findIndex(x => Number.isNaN(x))
0
> [NaN].find(x => Number.isNaN(x))
NaN
```
唉,没有简单的经验法则,你必须检查每个方法,它如何处理`NaN`。
### 15.7。错误值:`Infinity`
何时返回错误值`Infinity`?
如果数字太大,则返回无穷大:
```js
> Math.pow(2, 1023)
8.98846567431158e+307
> Math.pow(2, 1024)
Infinity
```
如果除以零,则返回无穷大:
```js
> 5 / 0
Infinity
> -5 / 0
-Infinity
```
#### 15.7.1。 `Infinity`作为默认值
`Infinity`大于所有其他数字(`NaN`除外),使其成为一个很好的默认值:
```js
function findMinimum(numbers) {
let min = Infinity;
for (const n of numbers) {
if (n < min) min = n;
}
return min;
}
assert.equal(findMinimum([5, -1, 2]), -1);
assert.equal(findMinimum([]), Infinity);
```
#### 15.7.2。检查`Infinity`
这是检查值`x`是否为`Infinity`的两种常用方法:
```js
const x = Infinity;
assert.equal(x === Infinity, true);
assert.equal(Number.isFinite(x), false);
```
![](https://img.kancloud.cn/3e/d5/3ed5755d562179ae6c199264f5e21157.svg) **练习:比较数字**
`exercises/numbers-math/find_max_test.js`
### 15.8。数字的精确度:小心小数
在内部,JavaScript 浮点数用基数 2 表示(根据 IEEE 754 标准)。这意味着小数部分(基数 10)不能总是精确表示:
```js
> 0.1 + 0.2
0.30000000000000004
> 1.3 * 3
3.9000000000000004
> 1.4 * 100000000000000
139999999999999.98
```
因此,在 JavaScript 中执行算术时需要考虑舍入误差。
继续阅读来解释这种现象。
![](https://img.kancloud.cn/ff/a8/ffa8e16628cad59b09c786b836722faa.svg) **测验:基本**
参见[测验应用程序](ch_quizzes-exercises.html#quizzes)。
### 15.9。 (高级)
本章的所有其余部分都是高级的。
### 15.10。背景:浮点精度
在 JavaScript 中,使用数字进行计算并不总能产生精确的结果。例如:
```js
> 0.1 + 0.2
0.30000000000000004
```
要理解原因,我们需要探索 JavaScript 如何在内部表示浮点数。它使用三个整数来执行此操作,如表 5 中所述。
表 5:在内部,JavaScript 使用三个整数来表示浮点数。它们总共占用 64 位存储空间(双精度)。
| 成分 | 大小 | 整数范围 |
| --- | --- | --- |
| 符号 | 1 位 | `[0,1]` |
| 小数 | 52 位 | `[0,2 ** 52 -1]` |
| 指数 | 11 位 | `[-1023,1024]` |
由这些整数表示的浮点数计算如下:
> `(-1) ** 符号 * 0b1.小数 * 2 ** 指数`
为了进一步讨论,我们简化了这种表示:
* 我们使用基数 10(十进制)代替基数 2(二进制),因为这是大多数人更熟悉的。
* *小数*是一个解释为小数的自然数(一个点后的数字)。我们切换到*尾数*,这是一个被解释为自身的整数。因此,指数的使用方式不同,但其基本作用不会改变。
* 由于尾数是一个整数(有自己的符号),我们不再需要单独的符号了。
新表示的工作方式如下:
> `尾数 * 10 ** 指数`
让我们试试几个浮点数的表示。
* 对于整数`-123`,我们主要需要尾数:
```js
> -123 * (10 ** 0)
-123
```
* 对于数字`1.5`,我们想象尾数后面有一个点。我们使用负指数将该点向左移动一位:
```js
> 15 * (10 ** -1)
1.5
```
* 对于数字`0.25`,我们将点向右移动两位数:
```js
> 25 * (10 ** -2)
0.25
```
具有负指数的表示也可以写为分母中具有正指数的分数:
```js
> 15 * (10 ** -1) === 15 / 10
true
> 25 * (10 ** -2) === 25 / 100
true
```
这些分数有助于理解为什么我们的编码无法表示数字:
* 可以表示`1/10`。它已经具有所需的格式:分母是 10 的幂。
* `1/2`可以表示为`5/10`。我们通过将分子和分母乘以 5,将分母中的 2 变为 10 的幂。
* `1/4`可以表示为`25/100`。通过将分子和分母乘以 25,我们将分母中的 4 变为 10 的幂。
* `1/3`无法表示。没有办法将分母变为 10 的幂。(10 的素数因子是 2 和 5。因此,任何只有这些素数因子的分母都可以通过使用足够的二和五乘以分子和分母,来转换为 10 的幂。如果分母有不同的素因子,那么我们无能为力。)
为了结束游览,我们切换回基数 2:
* `0.5 = 1/2`可以用基数 2 表示,因为分母已经是 2 的幂。
* `0.25 = 1/4`可以用基数 2 表示,因为分母已经是 2 的幂。
* 无法表示`0.1 = 1/10`,因为分母无法转换为 2 的幂。
* 无法表示`0.2 = 2/10`,因为分母无法转换为 2 的幂。
现在我们可以看到为什么`0.1 + 0.2`不能产生精确的结果:在内部,两个操作数都不能精确表示。
精确计算小数分数的唯一方法是通过内部切换到基数 10。对于许多编程语言,基数 2 是默认值,基数 10 是一个选项。例如,Java 具有类[`BigDecimal`](https://docs.oracle.com/javase/8/docs/api/java/math/BigDecimal.html) ,Python 具有模块 [`decimal`](https://docs.python.org/3/library/decimal.html)。JavaScript 暂时有计划添加类似的东西:ECMAScript 提案“Decimal”目前在[阶段 0](https://github.com/tc39/proposals/blob/master/stage-0-proposals.md)。
### 15.11。 JavaScript 中的整数
JavaScript 没有特殊的整数类型。相反,它们只是没有小数部分的正常(浮点)数字:
```js
> 1 === 1.0
true
> Number.isInteger(1.0)
true
```
在本节中,我们将介绍一些使用这些伪整数的工具。
#### 15.11.1。转换为整数
将数字转换为整数的推荐方法是使用`Math`对象的一种舍入方法(在[下一章](ch_math.html)中记录):
* `Math.floor(n)`:返回`i ≤ n`的最大整数
```js
> Math.floor(2.1)
2
> Math.floor(2.9)
2
```
* `Math.ceil(n)`:返回`i ≥ n`的最小整数
```js
> Math.ceil(2.1)
3
> Math.ceil(2.9)
3
```
* `Math.round(n)`:返回“最接近”`n`的整数。0.5 向上舍入。例如:
```js
> Math.round(2.4)
2
> Math.round(2.5)
3
```
* `Math.trunc(n)`:删除`n`具有的任何小数部分(在小数点之后),因此将其转换为整数。
```js
> Math.trunc(2.1)
2
> Math.trunc(2.9)
2
```
表 6 显示这些函数的各种输入的结果。
表 6: 将数字转换为整数的函数。 注意事情如何随负数变化,因为“较大”总是意味着“接近正无穷大”。
| | `-2.9` | `-2.5` | `-2.1` | `2.1` | `2.5` | `2.9` |
| --- | --- | --- | --- | --- | --- | --- |
| `Math.floor` | `-3` | `-3` | `-3` | `2` | `2` | `2` |
| `Math.ceil` | `-2` | `-2` | `-2` | `3` | `3` | `3` |
| `Math.round` | `-3` | `-2` | `-2` | `2` | `3` | `3` |
| `Math.trunc` | `-2` | `-2` | `-2` | `2` | `2` | `2` |
#### 15.11.2。 JavaScript 中的整数范围
这些是 JavaScript 中重要的整数范围:
* **安全整数:**可以通过 JavaScript“安全地”表示(意味着什么后面会讲更多)
* 精度:53 位带符号
* 范围:`(-2 ** 53 ~ 2 ** 53)`
* **数组索引**
* 精度:32 位,无符号
* 范围:`[0, 2 ** 32 - 1)`(不包括最大长度)
* 类型数组有更大的 53 位范围(安全和无符号)
* **按位操作数**(按位或,等等)
* 精度:32 位
* 无符号右移范围(`>>>`):无符号,`[0, 2 ** 32)`
* 所有其他按位运算符的范围:有符号,`[-2 ** 31, 2 ** 31)`
#### 15.11.3。安全整数
这是 JavaScript 中*安全*的整数范围:
> `[-2 ** 53 - 1, 2 ** 53 - 1]`
如果一个整数是*安全*的,则它只由一个 JavaScript 数字表示。鉴于 JavaScript 数字被编码为小数乘以二的指数次幂,也可以表示更高的整数,但它们之间存在间隙。
例如(18014398509481984 是`2 ** 54`):
```js
> 18014398509481984
18014398509481984
> 18014398509481985
18014398509481984
> 18014398509481986
18014398509481984
> 18014398509481987
18014398509481988
```
`Number`的以下属性有助于确定整数是否安全:
```js
assert.equal(Number.MAX_SAFE_INTEGER, (2 ** 53) - 1);
assert.equal(Number.MIN_SAFE_INTEGER, -Number.MAX_SAFE_INTEGER);
assert.equal(Number.isSafeInteger(5), true);
assert.equal(Number.isSafeInteger('5'), false);
assert.equal(Number.isSafeInteger(5.1), false);
assert.equal(Number.isSafeInteger(Number.MAX_SAFE_INTEGER), true);
assert.equal(Number.isSafeInteger(Number.MAX_SAFE_INTEGER+1), false);
```
![](https://img.kancloud.cn/3e/d5/3ed5755d562179ae6c199264f5e21157.svg) **练习:检测安全整数**
`exercises/numbers-math/is_safe_integer_test.js`
##### 15.11.3.1。安全的计算
让我们看一下涉及不安全整数的计算。
以下结果不正确且不安全,即使它的两个操作数都是安全的。
```js
> 9007199254740990 + 3
9007199254740992
```
以下结果是安全的,但不正确。第一个操作数是不安全的,第二个操作数是安全的。
```js
> 9007199254740995 - 10
9007199254740986
```
因此,当且仅当两个操作数和结果都是安全的时,表达式`a op b`的结果才是正确的:
```js
isSafeInteger(a) && isSafeInteger(b) && isSafeInteger(a op b)
```
### 15.12。按位运算符
JavaScript 按位运算符的工作方式如下:
* 首先,操作数转换为数字(64 位双浮点数),然后转换为 32 位整数。
* 然后执行按位操作。
* 最后,结果将转换回双精度并返回。
在内部,运算符使用以下整数范围(输入和输出):
* 无符号右移运算符(`>>>`):32 位,范围`[0, 2 ** 32)`
* 所有其他按位运算符:32 位包括符号,范围`[-2 ** 31, 2 ** 31)`
如果我们以二进制表示法将它们显示为无符号 32 位整数,则其中一些运算符的结果最容易理解。这就是`b32()`的作用(其实现将在后面显示):
```js
assert.equal(
b32(-1),
'11111111111111111111111111111111');
assert.equal(
b32(1),
'00000000000000000000000000000001');
assert.equal(
b32(2 ** 31),
'10000000000000000000000000000000');
```
#### 15.12.1。二元按位运算符
表 7:二进制按位运算符
| 运算符 | 名称 |
| --- | --- |
| `num1 & num2` | 按位和 |
| <code>num1 | num2</code> | 按位或 |
| `num1 ^ num2` | 按位异或 |
二元运算符(表 7 )组合其操作数的位来产生它们的结果:
```js
> (0b1010 & 0b11).toString(2).padStart(4, '0')
'0010'
> (0b1010 | 0b11).toString(2).padStart(4, '0')
'1011'
> (0b1010 ^ 0b11).toString(2).padStart(4, '0')
'1001'
```
#### 15.12.2。按位非
表 8 :按位非
| 运算符 | 名称 |
| --- | --- |
| `~num` | 按位非,补码 |
按位非运算符(表 8)反转其操作数的每个二进制位:
```js
> b32(~0b100)
'11111111111111111111111111111011'
```
#### 15.12.3。移位运算符
表 9:移位运算符
| 运算符 | 名称 |
| --- | --- |
| `num << count` | 左移 |
| `num >> count` | 有符号右移 |
| `num >>> count` | 无符号右移 |
移位运算符(表 9)向左或向右移动二进制位:
```js
> (0b10 << 1).toString(2)
'100'
```
`>>`保留最高位,`>>>`不保留:
```js
> b32(0b10000000000000000000000000000010 >> 1)
'11000000000000000000000000000001'
> b32(0b10000000000000000000000000000010 >>> 1)
'01000000000000000000000000000001'
```
#### 15.12.4。 `b32()`:以二进制表示法显示 32 位整数
我们现在使用了`b32()`几次。以下代码是它的实现。
```js
/**
* Return a string representing n as a 32-bit unsigned integer,
* in binary notation.
*/
function b32(n) {
// >>> ensures highest bit isn’t interpreted as a sign
return (n >>> 0).toString(2).padStart(32, '0');
}
assert.equal(
b32(6),
'00000000000000000000000000000110');
```
`n >>> 0`表示我们将`n`零位向右移位。因此,原则上,`>>>`运算符不执行任何操作,但它仍然将`n`强制转换为无符号的 32 位整数:
```js
> 12 >>> 0
12
> -12 >>> 0
4294967284
> (2**32 + 1) >>> 0
1
```
### 15.13。快速参考:数字
#### 15.13.1。转换为数字
表 10 显示如果通过`Number()`将各种值转换为数字会发生什么。
表 10:将值转换为数字
| `x` | `Number(x)` |
| --- | --- |
| `undefined` | `NaN` |
| `null` | `0` |
| 布尔值 | `false → 0`,`true → 1` |
| 数字 | `x`(无变化) |
| 字符串 | `'' → 0` |
| | 其他 → 解析的数字,忽略前导/尾随空格 |
| 对象 | 可配置的(例如通过`.valueOf()`) |
#### 15.13.2。算术运算符
JavaScript 有以下算术运算符:
* 二元算术运算符(表 11)
* 前缀和后缀算术运算符(表 12)
表 11:二元算术运算符
| 运算符 | 名称 | | 示例 |
| --- | --- | --- | --- |
| `n + m` | 加法 | ES1 | `3 + 4 → 7` |
| `n - m` | 减法 | ES1 | `9 - 1 → 8` |
| `n * m` | 乘法 | ES1 | `3 * 2.25 → 6.75` |
| `n / m` | 除法 | ES1 | `5.625 / 5 → 1.125` |
| `n % m` | 余数 | ES1 | `8 % 5 → 3` |
| | | | `-8 % 5 → -3` |
| `n ** m` | 幂 | ES2016 | `4 ** 2 → 16` |
表 12:前缀和后缀算术运算符
| 运算符 | 名称 | | 示例 |
| --- | --- | --- | --- |
| `+n` | 一元加 | ES1 | `+(-7) → -7` |
| `-n` | 一元减 | ES1 | `-(-7) → 7` |
| `v++` | 自增 | ES1 | `let v=0; [v++, v] → [0, 1]` |
| `++v` | 自增 | ES1 | `let v=0; [++v, v] → [1, 1]` |
| `v--` | 自减 | ES1 | `let v=1; [v--, v] → [1, 0]` |
| `--v` | 自减 | ES1 | `let v=1; [--v, v] → [0, 0]` |
#### 15.13.3。按位运算符
JavaScript 具有以下按位运算符:
* 按位和,或,异或,非(表 13)
* 移位运算符(表 14)
按位运算符的操作数和结果:
* 无符号右移运算符(`>>>`):32 位,范围`[0, 2 ** 32)`
* 所有其他按位运算符:32 位带符号,范围`[-2 ** 31, 2 ** 31)`
显示二进制数的辅助函数`b32()`在[本章前面的章节](ch_numbers.html#b32)中显示。
表 13:按位和,或,异或,非
| 运算符 | 名称 | | 示例 |
| --- | --- | --- | --- |
| `i & j` | 按位和 | ES1 | `(0b1010 & 0b1100).toString(2) → '1000'` |
| <code>i | j</code> | 按位或 | ES1 | <code>(0b1010 | 0b1100).toString(2) → '1110'</code> |
| `i ^ j` | 按位异或 | ES1 | `(0b1010 ^ 0b0011).toString(2) → '1001'` |
| `~i` | 按位非 | ES1 | `~0b11111111111111111111111111111110 → 1` |
表 14:移位运算符
| 运算符 | 名称 | | 示例 |
| --- | --- | --- | --- |
| `i << j` | 左移 | ES1 | `(0b1 << 1).toString(2) → '10'` |
| `i >> j` | 符号右移 | ES1 | `b32(0b10000000000000000000000000000010 >> 1)` |
| | | | `→ '11000000000000000000000000000001'` |
| `i >>> j` | 无符号右移 | ES1 | `b32(0b10000000000000000000000000000010 >>> 1)` |
| | | | `→ '01000000000000000000000000000001'` |
#### 15.13.4。数字的全局函数
JavaScript 具有以下四个全局函数:
* `isFinite()`
* `isNaN()`
* `parseFloat()`
* `parseInt()`
但是,最好使用`Number`的相应方法,这些方法具有较少的陷阱:`Number.isFinite()`,`Number.isNaN()`,`Number.parseFloat()`,`Number.parseInt()`。它们是与 ES6 一起引入的,将在下面讨论。
#### 15.13.5。 `Number`的静态属性
* `.EPSILON: number` <sup>[ES6]</sup>
1 和下一个可表示的浮点数之间的差异。通常,[机器的 epsilon](https://en.wikipedia.org/wiki/Machine_epsilon) 为浮点运算中的舍入误差提供上限。
* 大约为:`2.2204460492503130808472633361816 * 10 ** (-16)`
* `.MAX_SAFE_INTEGER: number` <sup>[ES6]</sup>
JavaScript 可以明确表示的最大整数(`2 ** 53 - 1`)。
* `.MAX_VALUE: number` <sup>[ES1]</sup>
最大的正有限 JavaScript 数。
* 大约为:`1.7976931348623157 * 10 ** 308`
* `.MIN_SAFE_INTEGER: number` <sup>[ES6]</sup>
JavaScript 可以明确表示的最小整数(`-2 ** 53 + 1`)。
* `.MIN_VALUE: number` <sup>[ES1]</sup>
最小的 JavaScript 正数。大约`5 * 10 ** -324`。
* `.NaN: number` <sup>[ES1]</sup>
与全局变量`NaN`相同。
* `.NEGATIVE_INFINITY: number` <sup>[ES1]</sup>
与`-Number.POSITIVE_INFINITY`相同。
* `.POSITIVE_INFINITY: number` <sup>[ES1]</sup>
与全局变量`Infinity`相同。
#### 15.13.6。 `Number`的静态方法
* `.isFinite(num: number): boolean` <sup>[ES6]</sup>
如果`num`是实际数字(不是`Infinity`,`-Infinity`和`NaN`),则返回`true`。
```js
> Number.isFinite(Infinity)
false
> Number.isFinite(-Infinity)
false
> Number.isFinite(NaN)
false
> Number.isFinite(123)
true
```
* `.isInteger(num: number): boolean` <sup>[ES6]</sup>
如果`num`是一个数字并且没有小数部分,则返回`true`。
```js
> Number.isInteger(-17)
true
> Number.isInteger(33)
true
> Number.isInteger(33.1)
false
> Number.isInteger('33')
false
> Number.isInteger(NaN)
false
> Number.isInteger(Infinity)
false
```
* `.isNaN(num: number): boolean` <sup>[ES6]</sup>
如果`num`是值`NaN`,则返回`true`:
```js
> Number.isNaN(NaN)
true
> Number.isNaN(123)
false
> Number.isNaN('abc')
false
```
* `.isSafeInteger(num: number): boolean` <sup>[ES6]</sup>
如果`num`是一个数字并且明确表示一个整数,则返回`true`。
* `.parseFloat(str: string): number` <sup>[ES6]</sup>
将其参数强制转换为字符串并将其解析为浮点数。为了将字符串转换为数字,`Number()`(忽略前导和尾随空格)通常是比`Number.parseFloat()`更好的选择(它忽略前导空格和非法尾随字符并且可以隐藏问题)。
```js
> Number.parseFloat(' 123.4#')
123.4
> Number(' 123.4#')
NaN
```
* `.parseInt(str: string, radix=10): number` <sup>[ES6]</sup>
将其参数强制转换为字符串并将其解析为整数,忽略前导空格和非法尾随字符:
```js
> Number.parseInt(' 123#')
123
```
参数`radix`指定要解析的数字的基数:
```js
> Number.parseInt('101', 2)
5
> Number.parseInt('FF', 16)
255
```
不要使用此方法将数字转换为整数:强制转换为字符串是低效的。并且在第一个非数字之前停止,不是用于移除数字的小数的良好算法。这是一个出错的例子:
```js
> Number.parseInt(1e21, 10) // wrong
1
```
最好使用`Math`的一个舍入函数将数字转换为整数:
```js
> Math.trunc(1e21) // correct
1e+21
```
#### 15.13.7。 `Number.prototype`的方法
* `.toExponential(fractionDigits?: number): string` <sup>[ES3]</sup>
返回一个字符串,该字符串通过指数表示法表示数字。使用`fractionDigits`,您可以指定与指数相乘的数字的位数(默认值是根据需要显示位数)。
示例:数字太小而无法通过`.toString()`获得正指数。
```js
> 1234..toString()
'1234'
> 1234..toExponential()
'1.234e+3'
> 1234..toExponential(5)
'1.23400e+3'
```
示例:数字太小而无法通过`.toString()`得到负指数。
```js
> 0.003.toString()
'0.003'
> 0.003.toExponential()
'3e-3'
> 0.003.toExponential(4)
'3.0000e-3'
```
* `.toFixed(fractionDigits=0): string` <sup>[ES3]</sup>
返回数字的无指数表示,舍入为`fractionDigits`个数字。
```js
> 0.0000003.toString()
'3e-7'
> 0.0000003.toFixed(10)
'0.0000003000'
> 0.0000003.toFixed()
'0'
```
如果数字为`10 ** 21` 或更高,则`.toFixed()`使用指数:
```js
> (10 ** 21).toFixed()
'1e+21'
```
* `.toPrecision(precision?: number): string` <sup>[ES3]</sup>
像`.toString()`一样工作,但在返回结果之前将尾数修剪为数字`precision`。如果缺少`precision`,则使用`.toString()`。
```js
> 1234..toPrecision(3) // requires exponential notation
'1.23e+3'
> 1234..toPrecision(4)
'1234'
> 1234..toPrecision(5)
'1234.0'
> 1.234.toPrecision(3)
'1.23'
```
* `.toString(radix=10): string` <sup>[ES1]</sup>
返回数字的字符串表示形式。
返回基数为 10 的结果:
```js
> 123.456.toString()
'123.456'
```
使用 10 以外的基数返回结果(通过`radix`指定):
```js
> 4..toString(2)
'100'
> 4.5.toString(2)
'100.1'
> 255..toString(16)
'ff'
> 255.66796875.toString(16)
'ff.ab'
> 1234567890..toString(36)
'kf12oi'
```
您可以使用`parseInt()`将整数结果转换回数字:
```js
> parseInt('kf12oi', 36)
1234567890
```
#### 15.13.8。来源
* 维基百科
* [TypeScript 的内置类型](https://github.com/Microsoft/TypeScript/blob/master/lib/)
* [JavaScript 的 MDN 网络文档](https://developer.mozilla.org/en-US/docs/Web/JavaScript)
* [ECMAScript 语言规范](https://tc39.github.io/ecma262/)
![](https://img.kancloud.cn/ff/a8/ffa8e16628cad59b09c786b836722faa.svg) **测验:高级**
参见[测验应用程序](ch_quizzes-exercises.html#quizzes)。
- I.背景
- 1.关于本书(ES2019 版)
- 2.常见问题:本书
- 3. JavaScript 的历史和演变
- 4.常见问题:JavaScript
- II.第一步
- 5.概览
- 6.语法
- 7.在控制台上打印信息(console.*)
- 8.断言 API
- 9.测验和练习入门
- III.变量和值
- 10.变量和赋值
- 11.值
- 12.运算符
- IV.原始值
- 13.非值undefined和null
- 14.布尔值
- 15.数字
- 16. Math
- 17. Unicode - 简要介绍(高级)
- 18.字符串
- 19.使用模板字面值和标记模板
- 20.符号
- V.控制流和数据流
- 21.控制流语句
- 22.异常处理
- 23.可调用值
- VI.模块化
- 24.模块
- 25.单个对象
- 26.原型链和类
- 七.集合
- 27.同步迭代
- 28.数组(Array)
- 29.类型化数组:处理二进制数据(高级)
- 30.映射(Map)
- 31. WeakMaps(WeakMap)
- 32.集(Set)
- 33. WeakSets(WeakSet)
- 34.解构
- 35.同步生成器(高级)
- 八.异步
- 36. JavaScript 中的异步编程
- 37.异步编程的 Promise
- 38.异步函数
- IX.更多标准库
- 39.正则表达式(RegExp)
- 40.日期(Date)
- 41.创建和解析 JSON(JSON)
- 42.其余章节在哪里?