From 507269f8c72cea087d5675994555b5edf27834a7 Mon Sep 17 00:00:00 2001 From: LeviDing Date: Mon, 6 Apr 2020 12:38:06 +0800 Subject: [PATCH 01/25] Update article.md --- 1-js/05-data-types/02-number/article.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/1-js/05-data-types/02-number/article.md b/1-js/05-data-types/02-number/article.md index 2a43e8cefd..b1be62d4a2 100644 --- a/1-js/05-data-types/02-number/article.md +++ b/1-js/05-data-types/02-number/article.md @@ -1,8 +1,12 @@ # 数字类型 -JavaScript 中的所有数字都以 64 位格式 [IEEE-754](http://en.wikipedia.org/wiki/IEEE_754-1985) 存储,也称为“双精度”。 +在现代 JavaScript 中,数字(number)有两种类型: -让我们回顾一下并展开我们目前了解的内容。 +1. JavaScript 中的常规数字以 64 位的格式 [IEEE-754](https://en.wikipedia.org/wiki/IEEE_754-2008_revision) 存储,也被称为“双精度浮点数”。这是我们大多数时候所使用的数字,我们将在本章中学习它们。 + +2. BigInt 数字代表任意长度的整数。有时会需要它们,因为常规数字不能超过 253 或小于 -253。由于仅在少数特殊领域才会用到 BigInt,因此我们在特殊的章节 中对其进行了介绍。 + +所以,在这里我们将讨论常规数字类型。现在让我们开始学习吧。 ## 编写数字的更多方法 From 1746a25fe1b996758b26eaeea72fd2a4e9ebe166 Mon Sep 17 00:00:00 2001 From: LeviDing Date: Mon, 6 Apr 2020 12:57:26 +0800 Subject: [PATCH 02/25] Update article.md --- 1-js/05-data-types/02-number/article.md | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/1-js/05-data-types/02-number/article.md b/1-js/05-data-types/02-number/article.md index b1be62d4a2..4a3c3cd881 100644 --- a/1-js/05-data-types/02-number/article.md +++ b/1-js/05-data-types/02-number/article.md @@ -10,30 +10,29 @@ ## 编写数字的更多方法 -想象一下,我们需要写 10 亿。显而易见的方法是: +想象一下,我们需要写 10 亿。显然的方法是: ```js let billion = 1000000000; ``` -但在现实生活中,我们通常避免写一长串零,因为它很容易输入错误。另外,我们很懒。我们通常会为十亿或七十三亿写一些类似于 `1bn` 的数字,为 `7.3bn`。对于大多数人来说也是如此。 +但在现实生活中,我们通常避免写一长串零,因为它很容易打错。另外,我们很懒。我们通常会将 10 亿写成 `"1bn"`,或将 72 亿写成 `7.3bn`。对于大多数大的数字来说都是如此。 -在 JavaScript 中,我们通过在数字后附加字母 "e" 来缩短数字,并指定零的数量来计数: +在 JavaScript 中,我们通过在数字后附加字母 "e",并指定零的数量来缩短数字: ```js run -let billion = 1e9; // 1 billion, literally: 1 and 9 zeroes +let billion = 1e9; // 10 亿,字面意思:数字 1 后面跟 9 个 0 -alert( 7.3e9 ); // 7.3 billions (7,300,000,000) +alert( 7.3e9 ); // 73 亿(7,300,000,000) ``` -换句话说,`"e"` 把数字乘以 `1` 后面跟着指定数量的 0。 +换句话说,`"e"` 把数字乘以 `1` 后面跟着指定数量的 0 的数字。 ```js 1e3 = 1 * 1000 -1.23e6 = 1.23 * 1000000 +1.23e6 = 1.23 * 1000000 ``` - 现在让我们写一些非常小的东西。例如:1 微秒(百万分之一秒): ```js let ms = 0.000001; From 9a9d88445d71bbf8c2667d1a63e5eea569934336 Mon Sep 17 00:00:00 2001 From: LeviDing Date: Mon, 6 Apr 2020 13:01:43 +0800 Subject: [PATCH 03/25] Fix typo --- 1-js/05-data-types/07-map-set/article.md | 66 ++++++++++++------------ 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/1-js/05-data-types/07-map-set/article.md b/1-js/05-data-types/07-map-set/article.md index 0b8b89a419..f1f1de77ce 100644 --- a/1-js/05-data-types/07-map-set/article.md +++ b/1-js/05-data-types/07-map-set/article.md @@ -14,13 +14,13 @@ 它的方法和属性如下: -- `new Map()` - 创建 map。 -- `map.set(key, value)` - 根据键存储值。 -- `map.get(key)` - 根据键来返回值,如果 `map` 中不存在对应的 `key`,则返回 `undefined`。 -- `map.has(key)` - 如果 `key` 存在则返回 `true`,否则返回 `false`。 -- `map.delete(key)` - 删除指定键的值。 -- `map.clear()` - 清空 map。 -- `map.size` - 返回当前元素个数。 +- `new Map()` —— 创建 map。 +- `map.set(key, value)` —— 根据键存储值。 +- `map.get(key)` —— 根据键来返回值,如果 `map` 中不存在对应的 `key`,则返回 `undefined`。 +- `map.has(key)` —— 如果 `key` 存在则返回 `true`,否则返回 `false`。 +- `map.delete(key)` —— 删除指定键的值。 +- `map.clear()` —— 清空 map。 +- `map.size` —— 返回当前元素个数。 举个例子: @@ -103,9 +103,9 @@ map.set('1', 'str1') 如果要在 `map` 里使用循环,可以使用以下三个方法: -- `map.keys()` - 遍历并返回所有的键(returns an iterable for keys), -- `map.values()` - 遍历并返回所有的值(returns an iterable for values), -- `map.entries()` - 遍历并返回所有的实体(returns an iterable for entries)`[key, value]`,`for..of` 在默认情况下使用的就是这个。 +- `map.keys()` —— 遍历并返回所有的键(returns an iterable for keys), +- `map.values()` —— 遍历并返回所有的值(returns an iterable for values), +- `map.entries()` —— 遍历并返回所有的实体(returns an iterable for entries)`[key, value]`,`for..of` 在默认情况下使用的就是这个。 例如: @@ -235,12 +235,12 @@ let obj = Object.fromEntries(map); // 省掉 .entries() 它的主要方法如下: -- `new Set(iterable)` - 创建一个 `set`,如果提供了一个 `iterable` 对象(通常是数组),将会从数组里面复制值到 `set` 中。 -- `set.add(value)` - 添加一个值,返回 set 本身 -- `set.delete(value)` - 删除值,如果 `value` 在这个方法调用的时候存在则返回 `true` ,否则返回 `false`。 -- `set.has(value)` - 如果 `value` 在 set 中,返回 `true`,否则返回 `false`。 -- `set.clear()` - 清空 set。 -- `set.size` - 返回元素个数。 +- `new Set(iterable)` —— 创建一个 `set`,如果提供了一个 `iterable` 对象(通常是数组),将会从数组里面复制值到 `set` 中。 +- `set.add(value)` —— 添加一个值,返回 set 本身 +- `set.delete(value)` —— 删除值,如果 `value` 在这个方法调用的时候存在则返回 `true` ,否则返回 `false`。 +- `set.has(value)` —— 如果 `value` 在 set 中,返回 `true`,否则返回 `false`。 +- `set.clear()` —— 清空 set。 +- `set.size` —— 返回元素个数。 它的主要特点是,重复使用同一个值调用 `set.add(value)` 并不会发生什么改变。这就是 `Set` 里面的每一个值只出现一次的原因。 @@ -293,9 +293,9 @@ set.forEach((value, valueAgain, set) => { `Map` 中用于迭代的方法在 `Set` 中也同样支持: -- `set.keys()` - 遍历并返回所有的值(returns an iterable object for values), -- `set.values()` - 与 `set.keys()` 作用相同,这是为了兼容 `Map`, -- `set.entries()` - 遍历并返回所有的实体(returns an iterable object for entries)`[value, value]`,它的存在也是为了兼容 `Map`。 +- `set.keys()` —— 遍历并返回所有的值(returns an iterable object for values), +- `set.values()` —— 与 `set.keys()` 作用相同,这是为了兼容 `Map`, +- `set.entries()` —— 遍历并返回所有的实体(returns an iterable object for entries)`[value, value]`,它的存在也是为了兼容 `Map`。 ## 总结 @@ -303,28 +303,28 @@ set.forEach((value, valueAgain, set) => { 方法和属性如下: -- `new Map([iterable])` - 创建 map,可选择带有 `[key,value]` 对的 `iterable`(例如数组)来进行初始化。 -- `map.set(key, value)` - 根据键存储值。 -- `map.get(key)` - 根据键来返回值,如果 `map` 中不存在对应的 `key`,则返回 `undefined`。 -- `map.has(key)` - 如果 `key` 存在则返回 `true`,否则返回 `false`。 -- `map.delete(key)` - 删除指定键的值。 -- `map.clear()` - 清空 map 。 -- `map.size` - 返回当前元素个数。 +- `new Map([iterable])` —— 创建 map,可选择带有 `[key,value]` 对的 `iterable`(例如数组)来进行初始化。 +- `map.set(key, value)` —— 根据键存储值。 +- `map.get(key)` —— 根据键来返回值,如果 `map` 中不存在对应的 `key`,则返回 `undefined`。 +- `map.has(key)` —— 如果 `key` 存在则返回 `true`,否则返回 `false`。 +- `map.delete(key)` —— 删除指定键的值。 +- `map.clear()` —— 清空 map 。 +- `map.size` —— 返回当前元素个数。 与普通对象 `Object` 的不同点: - 任何键、对象都可以作为键。 - 有其他的便捷方法,如 `size` 属性。 -`Set` - 是一组唯一值的集合。 +`Set` —— 是一组唯一值的集合。 方法和属性: -- `new Set([iterable])` - 创建 set,可选择带有 `iterable`(例如数组)来进行初始化。 -- `set.add(value)` - 添加一个值(如果 `value` 存在则不做任何修改),返回 set 本身。 -- `set.delete(value)` - 删除值,如果 `value` 在这个方法调用的时候存在则返回 `true` ,否则返回 `false`。 -- `set.has(value)` - 如果 `value` 在 set 中,返回 `true`,否则返回 `false`。 -- `set.clear()` - 清空 set。 -- `set.size` - 元素的个数。 +- `new Set([iterable])` —— 创建 set,可选择带有 `iterable`(例如数组)来进行初始化。 +- `set.add(value)` —— 添加一个值(如果 `value` 存在则不做任何修改),返回 set 本身。 +- `set.delete(value)` —— 删除值,如果 `value` 在这个方法调用的时候存在则返回 `true` ,否则返回 `false`。 +- `set.has(value)` —— 如果 `value` 在 set 中,返回 `true`,否则返回 `false`。 +- `set.clear()` —— 清空 set。 +- `set.size` —— 元素的个数。 在 `Map` 和 `Set` 中迭代总是按照值插入的顺序进行的,所以我们不能说这些集合是无序的,但是我们不能对元素进行重新排序,也不能直接按其编号来获取元素。 From 88e834b1771fff8cef4b37731d263969e1ada336 Mon Sep 17 00:00:00 2001 From: LeviDing Date: Mon, 6 Apr 2020 13:14:21 +0800 Subject: [PATCH 04/25] Update article.md --- 1-js/05-data-types/02-number/article.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/1-js/05-data-types/02-number/article.md b/1-js/05-data-types/02-number/article.md index 4a3c3cd881..b26c8623dc 100644 --- a/1-js/05-data-types/02-number/article.md +++ b/1-js/05-data-types/02-number/article.md @@ -26,34 +26,34 @@ let billion = 1e9; // 10 亿,字面意思:数字 1 后面跟 9 个 0 alert( 7.3e9 ); // 73 亿(7,300,000,000) ``` -换句话说,`"e"` 把数字乘以 `1` 后面跟着指定数量的 0 的数字。 +换句话说,`"e"` 把数字乘以 `1` 后面跟着给定数量的 0 的数字。 ```js 1e3 = 1 * 1000 1.23e6 = 1.23 * 1000000 ``` -现在让我们写一些非常小的东西。例如:1 微秒(百万分之一秒): +现在让我们写一些非常小的数字。例如,1 微秒(百万分之一秒): + ```js let ms = 0.000001; ``` -就像以前一样,使用 `"e"` 可以提供帮助。如果我们想避免明确地写零,我们可以说: +就像以前一样,可以使用 `"e"` 来完成。如果我们想避免显式地写零,我们可以这样写: ```js -let ms = 1e-6; // six zeroes to the left from 1 +let ms = 1e-6; // 1 的左边有 6 个 0 ``` +如果我们数一下 `0.000001` 中的 0 的个数,是 6 个。所以自然是 `1e-6`。 -如果我们计算 `0.000001` 中的零,则有 6 个。所以自然是 `1e-6`。 - -换句话说,`e` 后面的负数表示除以 1 后面跟着给定数量的 0: +换句话说,`e` 后面的负数表示除以 1 后面跟着给定数量的 0 的数字: ```js -// -3 divides by 1 with 3 zeroes +// -3 除以 1 后面跟着 3 个 0 的数字 1e-3 = 1 / 1000 (=0.001) -// -6 divides by 1 with 6 zeroes +// -6 除以 1 后面跟着 6 个 0 的数字 1.23e-6 = 1.23 / 1000000 (=0.00000123) ``` From 3d6235b027e0ffcecf5eff27ad67c5fc9c161fc7 Mon Sep 17 00:00:00 2001 From: LeviDing Date: Mon, 6 Apr 2020 15:35:51 +0800 Subject: [PATCH 05/25] Update article.md --- 1-js/05-data-types/02-number/article.md | 26 ++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/1-js/05-data-types/02-number/article.md b/1-js/05-data-types/02-number/article.md index b26c8623dc..4e18b5c381 100644 --- a/1-js/05-data-types/02-number/article.md +++ b/1-js/05-data-types/02-number/article.md @@ -59,30 +59,30 @@ let ms = 1e-6; // 1 的左边有 6 个 0 ### 十六进制,二进制和八进制数字 -[十六进制](https://en.wikipedia.org/wiki/Hexadecimal) 数字在 JavaScript 中被广泛用于表示颜色,编码字符以及其他许多事物。所以很自然地,写一个更简短的方法:`0x` 然后是数字。 +[十六进制](https://en.wikipedia.org/wiki/Hexadecimal) 数字在 JavaScript 中被广泛用于表示颜色,编码字符以及其他许多东西。所以自然地,有一种较短的写方法:`0x`,然后是数字。 例如: ```js run alert( 0xff ); // 255 -alert( 0xFF ); // 255 (the same, case doesn't matter) +alert( 0xFF ); // 255(一样,大小写没影响) ``` -虽然二进制和八进制数字系统很少使用,但也支持使用 `0b` 和 `0o` 前缀: +二进制和八进制数字系统很少使用,但也支持使用 `0b` 和 `0o` 前缀: ```js run -let a = 0b11111111; // binary form of 255 -let b = 0o377; // octal form of 255 +let a = 0b11111111; // 二进制形式的 255 +let b = 0o377; // 八进制形式的 255 -alert( a == b ); // true, the same number 255 at both sides +alert( a == b ); // true,两边是相同的数字,都是 255 ``` 只有这三种进制支持这种写法。对于其他进制,我们应该使用函数 `parseInt`(我们将在本章后面看到)。 ## toString(base) -方法 `num.toString(base)` 返回带有给定 `base` 的进制中 `num` 的字符串表示。 +方法 `num.toString(base)` 返回在给定 `base` 进制数字系统中 `num` 的字符串表示形式。 举个例子: ```js run @@ -92,24 +92,24 @@ alert( num.toString(16) ); // ff alert( num.toString(2) ); // 11111111 ``` -`base` 可以从 `2` 变到 `36`。默认情况下它是 `10`。 +`base` 的范围可以从 `2` 到 `36`。默认情况下是 `10`。 常见的用例如下: - **base=16** 用于十六进制颜色,字符编码等,数字可以是 `0..9` 或 `A..F`。 - **base=2** 主要用于调试按位操作,数字可以是 `0` 或 `1`。 -- **base=36** 是最大值,数字可以是 `0..9` 或 `A..Z`。整个拉丁字母用来表示一个数字。对于 `36` 来说,一个有趣而有用的例子是,当我们需要将一个较长的数字标识符变成较短的时候,例如做一个简短的URL。可以简单地用基数为 `36` 的数字系统表示: +- **base=36** 是最大进制,数字可以是 `0..9` 或 `A..Z`。所有拉丁字母都被用于了表示数字。对于 `36` 进制来说,一个有趣且有用的例子是,当我们需要将一个较长的数字标识符转换成较短的时候,例如做一个短的 URL。可以简单地使用基数为 `36` 的数字系统表示: ```js run alert( 123456..toString(36) ); // 2n9c ``` -```warn header="调用方法的两个点" -请注意 `123456..toString(36)` 中的两个点不是拼写错误。如果我们想直接在一个数字上调用一个方法,比如上面例子中的 `toString`,那么我们需要在它后面放置两个点 `..`。 +```warn header="使用两个点来调用一个方法" +请注意 `123456..toString(36)` 中的两个点不是打错了。如果我们想直接在一个数字上调用一个方法,比如上面例子中的 `toString`,那么我们需要在它后面放置两个点 `..`。 -如果我们放置一个点:`123456.toString(36)`,那么会出现错误,因为 JavaScript 语法暗示了第一个点之后的小数部分。如果我们再放一个点,那么 JavaScript 知道小数部分是空的,现在进入方法。 +如果我们放置一个点:`123456.toString(36)`,那么就会出现一个 error,因为 JavaScript 语法隐含了第一个点之后的部分为小数部分。如果我们再放一个点,那么 JavaScript 就知道小数部分为空,现在使用该方法。 -也可以写 `(123456).toString(36)`。 +也可以写成 `(123456).toString(36)`。 ``` ## 数值修约(Rounding) From 7e3b2fdded5be9a68f5686c5b83742980cc4938b Mon Sep 17 00:00:00 2001 From: LeviDing Date: Mon, 6 Apr 2020 15:54:08 +0800 Subject: [PATCH 06/25] Update article.md --- 1-js/05-data-types/01-primitives-methods/article.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/1-js/05-data-types/01-primitives-methods/article.md b/1-js/05-data-types/01-primitives-methods/article.md index c2073a66a0..02322d460f 100644 --- a/1-js/05-data-types/01-primitives-methods/article.md +++ b/1-js/05-data-types/01-primitives-methods/article.md @@ -70,7 +70,7 @@ alert( str.toUpperCase() ); // HELLO JavaScript 引擎高度优化了这个过程。它甚至可能跳过创建额外的对象。但是它仍然必须遵守规范,并且表现得好像它创建了一样。 -数字有其自己的方法,例如,[toFixed(n)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toFixed) 将数字四舍五入到给定的精度: +数字有其自己的方法,例如,[toFixed(n)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toFixed) 将数字舍入到给定的精度: ```js run let n = 1.23456; From 95eea6018defc61dd743d07aa1addff2176468db Mon Sep 17 00:00:00 2001 From: LeviDing Date: Mon, 6 Apr 2020 16:45:47 +0800 Subject: [PATCH 07/25] Update article.md --- 1-js/05-data-types/02-number/article.md | 80 ++++++++++++------------- 1 file changed, 39 insertions(+), 41 deletions(-) diff --git a/1-js/05-data-types/02-number/article.md b/1-js/05-data-types/02-number/article.md index 4e18b5c381..ce7b15dbae 100644 --- a/1-js/05-data-types/02-number/article.md +++ b/1-js/05-data-types/02-number/article.md @@ -112,11 +112,11 @@ alert( num.toString(2) ); // 11111111 也可以写成 `(123456).toString(36)`。 ``` -## 数值修约(Rounding) +## 舍入 -使用数字时最常用的操作之一是数值修约。 +舍入(rounding)是使用数字时最常用的操作之一。 -有几个内置的数值修约函数: +这里有几个对数字进行舍入的内建函数: `Math.floor` : 向下舍入:`3.1` 变成 `3`,`-1.1` 变成 `-2`。 @@ -125,12 +125,12 @@ alert( num.toString(2) ); // 11111111 : 向上舍入:`3.1` 变成 `4`,`-1.1` 变成 `-1`。 `Math.round` -: 向最近的整数舍入:`3.1` 变成 `3`, 3.6` 变成 `4`,`-1.1` 变成 `-1`。 +: 向最近的整数舍入:`3.1` 变成 `3`,`3.6` 变成 `4`,`-1.1` 变成 `-1`。 `Math.trunc`(IE 浏览器不支持这个方法) -: 删除小数点后的所有内容而不舍入:`3.1` 变成 `3`,`-1.1` 变成 `-1`。 +: 移除小数点后的所有内容而没有舍入:`3.1` 变成 `3`,`-1.1` 变成 `-1`。 -以下是总结它们之间差异的表格: +这个是总结它们之间差异的表格: | | `Math.floor` | `Math.ceil` | `Math.round` | `Math.trunc` | |---|---------|--------|---------|---------| @@ -140,22 +140,22 @@ alert( num.toString(2) ); // 11111111 |`-1.6`| `-2` | `-1` | `-2` | `-1` | -这些函数涵盖处理数字小数部分的所有可能方法。但是如果我们想在十进制后将数字四舍五入到 `n` 位呢? +这些函数涵盖了处理数字小数部分的所有可能方法。但是,如果我们想将数字舍入到小数点后 `n` 位,该怎么办? -例如,我们有 `1.2345`,并且想把它舍入到 2 位数,只得到 `1.23`。 +例如,我们有 `1.2345`,并且想把它舍入到小数点后两位,仅得到 `1.23`。 -有两种方法可以这样做: +有两种方式可以实现这个需求: -1. 乘法和除法 +1. 乘除法 - 例如,要将数字四舍五入到小数点后的第二个数字,我们可以将数字乘以 100,调用舍入函数,然后再将其除回 100。 + 例如,要将数字舍入到小数点后两位,我们可以将数字乘以 `100`,调用舍入函数,然后再将其除回。 ```js run let num = 1.23456; alert( Math.floor(num * 100) / 100 ); // 1.23456 -> 123.456 -> 123 -> 1.23 ``` -2. 函数 [toFixed(n)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toFixed) 将点数后的数字四舍五入到 `n` 个数字并返回结果的字符串表示。 +2. 函数 [toFixed(n)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toFixed) 将数字舍入到小数点后 `n` 位,并以字符串形式返回结果。 ```js run let num = 12.34; @@ -173,22 +173,22 @@ alert( num.toString(2) ); // 11111111 ```js run let num = 12.34; - alert( num.toFixed(5) ); // "12.34000", added zeroes to make exactly 5 digits + alert( num.toFixed(5) ); // "12.34000",在结尾添加了 0,以达到小数点后五位 ``` - 我们可以使用一元加号或 `Number()` 调用将其转换为数字:`+ num.toFixed(5)`。 + 我们可以使用一元加法或 `Number()` 调用,将其转换为数字:`+ num.toFixed(5)`。 -## 不精确计算 +## 不精确的计算 -在 js 内部,一个数字以 64 位格式 [IEEE-754](http://en.wikipedia.org/wiki/IEEE_754-1985) 表示,所以正好有 64 位可以存储一个数字:其中 52 个被使用存储这些数字,其中 11 个存储小数点的位置(它们对于整数为零),1 位用于符号。 +在内部,数字是以 64 位格式 [IEEE-754](http://en.wikipedia.org/wiki/IEEE_754-1985) 表示的,所以正好有 64 位可以存储一个数字:其中 52 位被用于存储这些数字,其中 11 位用于存储小数点的位置(对于整数,它们为零),而 1 位用于符号。 -如果一个数字太大,它会溢出 64 位存储,可能会输出无穷大: +如果一个数字太大,则会溢出 64 位存储,并可能会导致无穷大: ```js run -alert( 1e500 ); // Infinity +alert( 1e500 ); // Infinity ``` -可能不那么明显,但经常会发生精度的损失。 +这可能不那么明显,但经常会发生的是,精度的损失。 考虑下这个(falsy!)测试: @@ -196,51 +196,49 @@ alert( 1e500 ); // Infinity alert( 0.1 + 0.2 == 0.3 ); // *!*false*/!* ``` -没错,如果我们检查 `0.1` 和 `0.2` 的总和是否为 `0.3`,们会得到 `false`。 +没错,如果我们检查 `0.1` 和 `0.2` 的总和是否为 `0.3`,我们会得到 `false`。 -奇怪!那么如果不是 `0.3`,那么又是什么呢? +奇了怪了!如果不是 `0.3`,那能是啥? ```js run alert( 0.1 + 0.2 ); // 0.30000000000000004 ``` -哎哟!这里的错误有更大的误差。想象一下,你正在制作一个电子购物网站,访问者将 `0.10 美元` 和 `0.20 美元` 商品放入他的图表中。订单总额将是 `$ 0.30000000000000004`。这会让任何人感到惊讶。 +哎哟!这个错误比不正确的比较的后果更严重。想象一下,你创建了一个电子购物网站,如果访问者将价格为 `$ 0.10` 和 `$ 0.20` 的商品放入了他的购物车。订单总额将是 `$ 0.30000000000000004`。这会让任何人感到惊讶。 -但为什么会发生这样的事呢? +但为什么会这样呢? -一个数字以二进制形式存储在内存中,一个 1 和 0 的序列。但是像十进制数字系统看起来很简单的 `0.1`,`0.2` 这样的小数实际上是二进制形式的循环小数。 +一个数字以其二进制的形式存储在内存中,一个 1 和 0 的序列。但是在十进制数字系统中看起来很简单的 `0.1`,`0.2` 这样的小数,实际上在二进制形式中是无限循环小数。 -换句话说,什么是 `0.1`?`0.1` 就是把 1 除以 10 `1/10`,即十分之一。在十进制数字系统中,这些数字很容易表示。将它比作三分之一:`1/3`。它变成了循环小数 `0.33333(3)`。 +换句话说,什么是 `0.1`?`0.1` 就是 `1` 除以 `10`,`1/10`,即十分之一。在十进制数字系统中,这样的数字表示起来很容易。将其与三分之一进行比较:`1/3`。三分之一变成了无限循环小数 `0.33333(3)`。 -所以,按这种用 `10` 划分可以保证在十进制系统中运行良好,但用 `3` 划分不是。出于同样的原因,在二进制数字系统中,`2` 的幂的分割保证工作,但 `1/10` 变成一个无限的二进制小数。 +在十进制数字系统中,可以保证以 `10` 的整数次幂作为除数能够正常工作,但是以 `3` 作为除数则不能。也是同样的原因,在二进制数字系统中,可以保证以 `2` 的整数次幂作为除数时能够正常工作,但 `1/10` 就变成了一个无限循环的二进制小数。 -使用二进制系统无法*精确*存储 *0.1* 或 *0.2*,就像没有办法将三分之一存储为十进制小数一样。 +使用二进制数字系统无法 **精确** 存储 *0.1* 或 *0.2*,就像没有办法将三分之一存储为十进制小数一样。 -数字格式 IEEE-754 通过四舍五入到最接近的可能数字来解决此问题。这些舍入规则通常不允许我们看到 `极小的精确度损失`,因此数字显示为 `0.3`。但要小心,损失依然存在。 +IEEE-754 数字格式通过将数字舍入到最接近的可能数字来解决此问题。这些舍入规则通常不允许我们看到“极小的精度损失”,但是它确实存在。 -我们可以看到这一点: +我们可以看到: ```js run alert( 0.1.toFixed(20) ); // 0.10000000000000000555 ``` -当我们给两个数字求和时,他们的“精度损失”会加起来。 +当我们对两个数字进行求和时,它们的“精度损失”会叠加起来。 -这就是为什么 `0.1 + 0.2` 不等于 `0.3` 的原因。 +这就是为什么 `0.1 + 0.2` 不等于 `0.3`。 ```smart header="不仅仅是 JavaScript" 许多其他编程语言也存在同样的问题。 -PHP, Java, C, Perl, Ruby 给出完全相同的结果,因为它们基于相同的数字格式。 +PHP,Java,C,Perl,Ruby 给出的也是完全相同的结果,因为它们基于的是相同的数字格式。 ``` -我们能解决这个问题吗?当然,有很多方法: +我们能解决这个问题吗?当然,最可靠的方法是借助方法 [toFixed(n)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toFixed) 对结果进行舍入: -1. 我们可以在特定函数的帮助下对结果进行四舍五入 [toFixed(n)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toFixed): - - ```js run - let sum = 0.1 + 0.2; - alert( sum.toFixed(2) ); // 0.30 - ``` +```js run +let sum = 0.1 + 0.2; +alert( sum.toFixed(2) ); // 0.30 +``` 请注意 `toFixed` 总是返回一个字符串。它确保它在小数点后有 2 位数字。如果我们有电子购物并需要显示 `0.30 美元`,这实际上很方便。对于其他情况,我们可以使用一元加号将它强制为一个数字: @@ -327,7 +325,7 @@ alert( isFinite(num) ); ```smart header="与 Object.is 进行比较" -有一种特殊的内置方法 [`Object.is`](mdn:js/Object/is),它可以比较 `===` 等值,但对于两种边缘情况更可靠: +有一种特殊的内建方法 [`Object.is`](mdn:js/Object/is),它可以比较 `===` 等值,但对于两种边缘情况更可靠: 1. 它适用于 `NaN`: `Object.is(NaN,NaN)=== true`,这是件好事。 2. 值 `0` 和 `-0` 是不同的:`Object.is(0,-0)=== false`,它不是很重要,但这些值在技术上是不同的。 @@ -381,7 +379,7 @@ alert( parseInt('2n9c', 36) ); // 123456 ## 其他数学函数 -JavaScript 有一个内置的 [Math](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Math) 对象,它包含了一个小型的数学函数和常量库。 +JavaScript 有一个内建的 [Math](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Math) 对象,它包含了一个小型的数学函数和常量库。 几个例子: From 5832e8cf4f4bfe03eeaf28e309d1b1e5c75032ae Mon Sep 17 00:00:00 2001 From: LeviDing Date: Mon, 6 Apr 2020 17:51:19 +0800 Subject: [PATCH 08/25] Update article.md --- 1-js/05-data-types/02-number/article.md | 89 ++++++++++++------------- 1 file changed, 44 insertions(+), 45 deletions(-) diff --git a/1-js/05-data-types/02-number/article.md b/1-js/05-data-types/02-number/article.md index ce7b15dbae..9054397687 100644 --- a/1-js/05-data-types/02-number/article.md +++ b/1-js/05-data-types/02-number/article.md @@ -176,7 +176,7 @@ alert( num.toString(2) ); // 11111111 alert( num.toFixed(5) ); // "12.34000",在结尾添加了 0,以达到小数点后五位 ``` - 我们可以使用一元加法或 `Number()` 调用,将其转换为数字:`+ num.toFixed(5)`。 + 我们可以使用一元加号或 `Number()` 调用,将其转换为数字:`+ num.toFixed(5)`。 ## 不精确的计算 @@ -204,7 +204,7 @@ alert( 0.1 + 0.2 == 0.3 ); // *!*false*/!* alert( 0.1 + 0.2 ); // 0.30000000000000004 ``` -哎哟!这个错误比不正确的比较的后果更严重。想象一下,你创建了一个电子购物网站,如果访问者将价格为 `$ 0.10` 和 `$ 0.20` 的商品放入了他的购物车。订单总额将是 `$ 0.30000000000000004`。这会让任何人感到惊讶。 +哎哟!这个错误比不正确的比较的后果更严重。想象一下,你创建了一个电子购物网站,如果访问者将价格为 `¥ 0.10` 和 `¥ 0.20` 的商品放入了他的购物车。订单总额将是 `¥ 0.30000000000000004`。这会让任何人感到惊讶。 但为什么会这样呢? @@ -240,54 +240,53 @@ let sum = 0.1 + 0.2; alert( sum.toFixed(2) ); // 0.30 ``` - 请注意 `toFixed` 总是返回一个字符串。它确保它在小数点后有 2 位数字。如果我们有电子购物并需要显示 `0.30 美元`,这实际上很方便。对于其他情况,我们可以使用一元加号将它强制为一个数字: +请注意,`toFixed` 总是返回一个字符串。它确保小数点后有 2 位数字。如果我们有一个电子购物网站,并需要显示 `¥ 0.30`,这实际上很方便。对于其他情况,我们可以使用一元加号将其强制转换为一个数字: - ```js run - let sum = 0.1 + 0.2; - alert( +sum.toFixed(2) ); // 0.3 - ``` +```js run +let sum = 0.1 + 0.2; +alert( +sum.toFixed(2) ); // 0.3 +``` -2. 我们可以暂时将数字转换为数学整数,然后将其恢复。它是这样工作的: +我们可以将数字临时乘以 100(或更大的数字),将其转换为整数,进行数学运算,然后再除回。当我们使用整数进行数学运算时,误差会有所减少,但仍然可以在除法中得到: - ```js run - alert( (0.1 * 10 + 0.2 * 10) / 10 ); // 0.3 - alert( (0.28 * 100 + 0.14 * 100) / 100); // 0.4200000000000001 - ``` +```js run +alert( (0.1 * 10 + 0.2 * 10) / 10 ); // 0.3 +alert( (0.28 * 100 + 0.14 * 100) / 100); // 0.4200000000000001 +``` - 这是有效的,因为当我们做 `0.1 * 10 = 1` 和 `0.2 * 10 = 2` 时,那么这两个数字就变成了整数,并且没有精度损失。 +因此,乘/除法可以减少误差,但不能完全消除误差。 -3. 如果我们在与一家商店打交道,那么最激进的解决方案就是将所有价格存储在美分中,并且根本不使用分数。但是,如果我们应用 30% 的折扣呢?在实践中,完全回避分数是很难实现的,所以上述解决方案有助于避免这种缺陷。 +有时候我们可以尝试完全避免分数。例如,我们正在创建一个电子购物网站,那么我们可以用角而不是元来存储价格。但是,如果我们要打 30% 的折扣呢?实际上,完全避免分数处理几乎是不可能的。只需要在必要时剪掉其“尾巴”来对其进行舍入即可。 -````smart header="有趣的事情" -尝试运行这个: +````smart header="有趣的事儿" +尝试运行下面这段代码: ```js run -// Hello! I'm a self-increasing number! -alert( 9999999999999999 ); // shows 10000000000000000 +// Hello!我是一个会自我增加的数字! +alert( 9999999999999999 ); // 显示 10000000000000000 ``` -出现了同样的问题:精度的损失。该号码有 64 位,其中 52 位可用于存储数字,但这还不够。所以最不重要的数字就消失了。 +出现了同样的问题:精度损失。有 64 位来表示该数字,其中 52 位可用于存储数字,但这还不够。所以最不重要的数字就消失了。 -JavaScript 在这种事件中不会触发错误。它尽最大努力使数字符合所需的格式,但不幸的是,这种格式不够大到满足需求。 +JavaScript 不会在此类事件中触发 error。它会尽最大努力使数字符合所需的格式,但不幸的是,这种格式不够大到满足需求。 ```` ```smart header="两个零" 数字内部表示的另一个有趣结果是存在两个零:`0` 和 `-0`。 -这是因为一个符号由一个位表示,所以每个数字可以是正数或负数,包括零。 +这是因为在存储时,使用一位来存储符号,因此对于包括零在内的任何数字,可以设置这一位或者不设置。 -在大多数情况下,这种区别并不明显,因为操作员可以将它们视为相同。 +在大多数情况下,这种区别并不明显,因为运算符将它们视为相同的值。 ``` - ## 测试:isFinite 和 isNaN 还记得这两个特殊的数值吗? - `Infinity`(和 `-Infinity`)是一个特殊的数值,比任何数值都大(小)。 -- `NaN` 代表一个错误。 +- `NaN` 代表一个 error。 -它们属于 `数字` 类型,但不是 `普通` 数字,因此有特殊函数可以检查它们: +它们属于 `number` 类型,但不是“普通”数字,因此,这里有用于检查它们的特殊函数: - `isNaN(value)` 将其参数转换为数字,然后测试它是否为 `NaN`: @@ -297,42 +296,42 @@ JavaScript 在这种事件中不会触发错误。它尽最大努力使数字符 alert( isNaN("str") ); // true ``` - 但是我们需要这个功能吗?我们不能只使用比较 `=== NaN` 吗?对不起,但答案是否定的。值 "NaN" 是独一无二的,它不等于任何东西,包括它本身: + 但是我们需要这个函数吗?我们不能只使用 `=== NaN` 比较吗?不好意思,这不行。值 "NaN" 是独一无二的,它不等于任何东西,包括它自身: ```js run alert( NaN === NaN ); // false ``` -- `isFinite(value)` 将其参数转换为数字,如果是常规数字,则返回 `true`,而不是 `NaN / Infinity / -Infinity`: +- `isFinite(value)` 将其参数转换为数字,如果是常规数字,则返回 `true`,而不是 `NaN/Infinity/-Infinity`: ```js run alert( isFinite("15") ); // true - alert( isFinite("str") ); // false, because a special value: NaN - alert( isFinite(Infinity) ); // false, because a special value: Infinity + alert( isFinite("str") ); // false,因为是一个特殊的值:NaN + alert( isFinite(Infinity) ); // false,因为是一个特殊的值:Infinity ``` -有时 `isFinite` 用于验证字符串值是否为常规数字: +有时 `isFinite` 被用于验证字符串值是否为常规数字: ```js run let num = +prompt("Enter a number", ''); -// 结果会是 true,除非你输入无穷大、无穷小或不是数字 +// 结果会是 true,除非你输入的是 Infinity、-Infinity 或不是数字 alert( isFinite(num) ); ``` -请注意,所有数字函数(包括 `isFinite`)中的空字符串或空格字符串均被视为 `0`。 +请注意,在所有数字函数中,包括 `isFinite`,空字符串或仅有空格的字符串均被视为 `0`。 -```smart header="与 Object.is 进行比较" +```smart header="与 `Object.is` 进行比较" -有一种特殊的内建方法 [`Object.is`](mdn:js/Object/is),它可以比较 `===` 等值,但对于两种边缘情况更可靠: +有一个特殊的内建方法 [`Object.is`](mdn:js/Object/is),它类似于 `===` 一样对值进行比较,但它对于两种边缘情况更可靠: -1. 它适用于 `NaN`: `Object.is(NaN,NaN)=== true`,这是件好事。 -2. 值 `0` 和 `-0` 是不同的:`Object.is(0,-0)=== false`,它不是很重要,但这些值在技术上是不同的。 +1. 它适用于 `NaN`:`Object.is(NaN,NaN)=== true`,这是件好事。 +2. 值 `0` 和 `-0` 是不同的:`Object.is(0,-0)=== false`,从技术上讲这是对的,因为在内部,数字的符号位可能会不同,即使其他所有位均为零。 在所有其他情况下,`Object.is(a,b)` 与 `a === b` 相同。 -这种比较方式经常用于 JavaScript 规范。当内部算法需要比较两个值完全相同时,它使用 Object.is(内部称为 [同值相等(SameValue)](https://tc39.github.io/ecma262/#sec-samevalue))。 +这种比较方式经常被用在 JavaScript 规范中。当内部算法需要比较两个值是否完全相同时,它使用 `Object.is`(内部称为 [SameValue](https://tc39.github.io/ecma262/#sec-samevalue))。 ``` @@ -346,32 +345,32 @@ alert( +"100px" ); // NaN 唯一的例外是字符串开头或结尾的空格,因为它们会被忽略。 -但在现实生活中,我们经常以单位表示值,比如 CSS 中的 `"100px"` 或 `"12pt"`。在许多国家,货币符号也超过了金额,所以我们有 `"19€"`,并希望从中提取一个数值。 +但在现实生活中,我们经常会有带有单位的值,例如 CSS 中的 `"100px"` 或 `"12pt"`。并且,在很多国家,货币符号是紧随金额之后的,所以我们有 `"19€"`,并希望从中提取出一个数值。 这就是 `parseInt` 和 `parseFloat` 的作用。 -它们从字符串中“读出”一个数字,直到无法读取为止。如果发生错误,则返回收集的数字。函数 `parseInt` 返回一个整数,而 `parseFloat` 将返回一个浮点数: +它们可以从字符串中“读取”数字,直到无法读取为止。如果发生 error,则返回收集到的数字。函数 `parseInt` 返回一个整数,而 `parseFloat` 返回一个浮点数: ```js run alert( parseInt('100px') ); // 100 alert( parseFloat('12.5em') ); // 12.5 -alert( parseInt('12.3') ); // 12, only the integer part is returned -alert( parseFloat('12.3.4') ); // 12.3, the second point stops the reading +alert( parseInt('12.3') ); // 12,只有整数部分被返回了 +alert( parseFloat('12.3.4') ); // 12.3,在第二个点出停止了读取 ``` -有时候 `parseInt / parseFloat` 会返回 `NaN`。一般发生在没有数字可读的情况下: +某些情况下,`parseInt/parseFloat` 会返回 `NaN`。当没有数字可读时会发生这种情况: ```js run -alert( parseInt('a123') ); // NaN, the first symbol stops the process +alert( parseInt('a123') ); // NaN,第一个符号停止了读取 ``` ````smart header="parseInt(str, radix)` 的第二个参数" -`parseInt()` 函数有一个可选的第二个参数。它指定了数字系统的基础,因此 `parseInt` 还可以解析十六进制数字,二进制数字等字符串: +`parseInt()` 函数具有可选的第二个参数。它指定了数字系统的基数,因此 `parseInt` 还可以解析十六进制数字、二进制数字等的字符串: ```js run alert( parseInt('0xff', 16) ); // 255 -alert( parseInt('ff', 16) ); // 255, without 0x also works +alert( parseInt('ff', 16) ); // 255,没有 0x 仍然有效 alert( parseInt('2n9c', 36) ); // 123456 ``` From dc6b8a13b3483a88fa289cdc7c833dfd66f0b4fb Mon Sep 17 00:00:00 2001 From: LeviDing Date: Mon, 6 Apr 2020 17:57:39 +0800 Subject: [PATCH 09/25] Update article.md --- 1-js/05-data-types/02-number/article.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/1-js/05-data-types/02-number/article.md b/1-js/05-data-types/02-number/article.md index 9054397687..8dfb555a51 100644 --- a/1-js/05-data-types/02-number/article.md +++ b/1-js/05-data-types/02-number/article.md @@ -383,12 +383,12 @@ JavaScript 有一个内建的 [Math](https://developer.mozilla.org/en/docs/Web/J 几个例子: `Math.random()` -: 返回从 0 到 1 的随机数(不包括 1) +: 返回一个从 0 到 1 的随机数(不包括 1) ```js run alert( Math.random() ); // 0.1234567894322 alert( Math.random() ); // 0.5435252343232 - alert( Math.random() ); // ... (any random numbers) + alert( Math.random() ); // ... (任何随机数) ``` `Math.max(a, b, c...)` / `Math.min(a, b, c...)` @@ -400,17 +400,17 @@ JavaScript 有一个内建的 [Math](https://developer.mozilla.org/en/docs/Web/J ``` `Math.pow(n, power)` -: 返回 n 的 power 次幂,即 npower +: 返回 `n` 的给定(power)次幂 ```js run alert( Math.pow(2, 10) ); // 2 的 10 次幂 = 1024 ``` -这里有 `Math` 对象中的更多函数和常量,包括三角函数,你可以在 [Math 函数文档](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Math) 中找到这些内容。 +`Math` 对象中还有更多函数和常量,包括三角函数,你可以在 [Math 函数文档](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Math) 中找到这些内容。 ## 总结 -写非常大的数字: +要写有很多零的数字: - 附加 `"e"` 来省略 0,e 后面的数字就是零的个数。就像:`123e6` 是 `123` 后面接 6 个零。 - `"e"` 后面的负数将导致数字除以 1 后面接着给定数量的零。e-6 那是一百万分之一。 From 9f05b691790e5b6ca944b8b18b1fdaf62a0cb3ae Mon Sep 17 00:00:00 2001 From: LeviDing Date: Mon, 6 Apr 2020 18:43:04 +0800 Subject: [PATCH 10/25] Update article.md --- 1-js/05-data-types/02-number/article.md | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/1-js/05-data-types/02-number/article.md b/1-js/05-data-types/02-number/article.md index 8dfb555a51..e1cb711027 100644 --- a/1-js/05-data-types/02-number/article.md +++ b/1-js/05-data-types/02-number/article.md @@ -412,24 +412,24 @@ JavaScript 有一个内建的 [Math](https://developer.mozilla.org/en/docs/Web/J 要写有很多零的数字: -- 附加 `"e"` 来省略 0,e 后面的数字就是零的个数。就像:`123e6` 是 `123` 后面接 6 个零。 -- `"e"` 后面的负数将导致数字除以 1 后面接着给定数量的零。e-6 那是一百万分之一。 +- 将 `"e"` 和 0 的数量附加到数字后。就像:`123e6` 与 `123` 后面接 6 个 0 相同。 +- `"e"` 后面的负数将使数字除以 1 后面接着给定数量的零的数字。例如 `123e-6` 表示 `0.000123`(`123` 的百万分之一)。 -对于不同的进制: +对于不同的数字系统: -- 可以在十六进制(`0x`),八进制(`0o`)和二进制(`0b`)系统中直接写入数字。 -- `parseInt(str,base)` 解析来自任何数字系统的整数,其基数为:`2≤base≤36`。 -- `num.toString(base)` 将数字转换为数字系统中具有给定 `base` 的字符串。 +- 可以直接在十六进制(`0x`),八进制(`0o`)和二进制(`0b`)系统中写入数字。 +- `parseInt(str,base)` 将字符串 `str` 解析为在给定的 `base` 数字系统中的整数,`2≤base≤36`。 +- `num.toString(base)` 将数字转换为在给定的 `base` 数字系统中的字符串。 -将 `12pt` 和 `100px` 等值转换为数字: +要将 `12pt` 和 `100px` 之类的值转换为数字: -- 使用 `parseInt / parseFloat` 进行 `软` 转换,它从字符串中读取一个数字,然后返回错误发生前可以读取的值。 +- 使用 `parseInt/parseFloat` 进行“软”转换,它从字符串中读取数字,然后返回在发生 error 前可以读取到的值。 分数: -- 使用 `Math.floor`,`Math.ceil`,`Math.trunc`,`Math.round` 或 `num.toFixed(precision)` 截取。 -- 请记住,使用分数时会损失精度。 +- 使用 `Math.floor`,`Math.ceil`,`Math.trunc`,`Math.round` 或 `num.toFixed(precision)` 进行舍入。 +- 请确保记住使用分数时会损失精度。 -更多的数学函数: +更多数学函数: -- 需要时请参阅 [Math](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Math) 对象,虽然这个文档非常小,但是它可以满足基础的要求。 +- 需要时请查看 [Math](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Math) 对象。这个库很小,但是可以满足基本的需求。 From a3d4aae3cc5123e83ec0a46478344a1a97718864 Mon Sep 17 00:00:00 2001 From: LeviDing Date: Mon, 6 Apr 2020 21:23:37 +0800 Subject: [PATCH 11/25] Update task.md --- 1-js/05-data-types/02-number/1-sum-interface/task.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/1-js/05-data-types/02-number/1-sum-interface/task.md b/1-js/05-data-types/02-number/1-sum-interface/task.md index 123a44d6e1..02b067e292 100644 --- a/1-js/05-data-types/02-number/1-sum-interface/task.md +++ b/1-js/05-data-types/02-number/1-sum-interface/task.md @@ -2,10 +2,10 @@ importance: 5 --- -# 来自访客的总数 +# 来自访问者的数字的总和 创建一个脚本,提示访问者输入两个数字,然后显示它们的总和。 [demo] -提示:类型会有一个问题。 +P.S. 有一个类型陷阱。 From e17bfc43cc53b5947afc934811dafaf08b4f81ed Mon Sep 17 00:00:00 2001 From: LeviDing Date: Mon, 6 Apr 2020 21:42:59 +0800 Subject: [PATCH 12/25] Update solution.md --- 1-js/05-data-types/02-number/1-sum-interface/solution.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/1-js/05-data-types/02-number/1-sum-interface/solution.md b/1-js/05-data-types/02-number/1-sum-interface/solution.md index 96b2eef2cc..f9b6392c2f 100644 --- a/1-js/05-data-types/02-number/1-sum-interface/solution.md +++ b/1-js/05-data-types/02-number/1-sum-interface/solution.md @@ -7,6 +7,6 @@ let b = +prompt("The second number?", ""); alert( a + b ); ``` -注意一元符号 `+` 在 `prompt` 前面。它会把获取的值转换成数字。 +注意在 `prompt` 前面的一元加号 `+`。它将立即把值转换成数字。 -否则,`a` 和 `b` 会是字符串,它们的总和就是它们的连接,即:`“1”+“2”=“12”`。 +否则,`a` 和 `b` 将会是字符串,它们的总和将是它们的连接,即:`"1" + "2" = "12"`。 From c7e80e1d1495ab6d5fa0cb638af672e5d8f2d7e8 Mon Sep 17 00:00:00 2001 From: LeviDing Date: Mon, 6 Apr 2020 21:50:07 +0800 Subject: [PATCH 13/25] Update task.md --- 1-js/05-data-types/02-number/2-why-rounded-down/task.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/1-js/05-data-types/02-number/2-why-rounded-down/task.md b/1-js/05-data-types/02-number/2-why-rounded-down/task.md index 711704ff51..addb0bd52a 100644 --- a/1-js/05-data-types/02-number/2-why-rounded-down/task.md +++ b/1-js/05-data-types/02-number/2-why-rounded-down/task.md @@ -4,7 +4,7 @@ importance: 4 # 为什么 6.35.toFixed(1) == 6.3? -根据文档 `Math.round` 和 `toFixed`,最近的数字四舍五入:`0..4` 会被舍去,而 `5..9` 会前进一位。 +根据文档,`Math.round` 和 `toFixed` 都将数字舍入到最接近的数字:`0..4` 会被舍去,而 `5..9` 会进一位。 例如: @@ -12,10 +12,11 @@ importance: 4 alert( 1.35.toFixed(1) ); // 1.4 ``` -在下面的类似例子中,为什么 `6.35` 被四舍五入为 `6.3` 而不是 `6.4`? +在下面这个类似的示例中,为什么 `6.35` 被舍入为 `6.3` 而不是 `6.4`? ```js run alert( 6.35.toFixed(1) ); // 6.3 ``` -如何以正确的方式来四舍五入 `6.35`? +如何以正确的方式来对 `6.35` 进行舍入? + From 978bc0d77cc8e587835c5d6fb2949ae1cc677da2 Mon Sep 17 00:00:00 2001 From: LeviDing Date: Tue, 7 Apr 2020 08:56:32 +0800 Subject: [PATCH 14/25] Update solution.md --- .../02-number/2-why-rounded-down/solution.md | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/1-js/05-data-types/02-number/2-why-rounded-down/solution.md b/1-js/05-data-types/02-number/2-why-rounded-down/solution.md index 2154378fdf..a107ec9407 100644 --- a/1-js/05-data-types/02-number/2-why-rounded-down/solution.md +++ b/1-js/05-data-types/02-number/2-why-rounded-down/solution.md @@ -1,4 +1,4 @@ -在 `6.35` 内部,小数部分是一个无限的二进制。在这种情况下,它存储的时候有一个精度的缺失。 +在内部,`6.35` 的小数部分是一个无限的二进制。在这种情况下,它的存储会造成精度损失。 让我们来看看: @@ -6,27 +6,28 @@ alert( 6.35.toFixed(20) ); // 6.34999999999999964473 ``` -精度缺失可能会导致数字的增加和减小。在这种特殊情况下,数字可能会变小了一点,这就是为什么它减小了。 +精度损失可能会导致数字的增加和减小。在这种特殊的情况下,数字变小了一点,这就是它向下舍入的原因。 -那么 `1.35` 是怎样的呢? +那么 `1.35` 会怎样呢? ```js run alert( 1.35.toFixed(20) ); // 1.35000000000000008882 ``` -在这里,精度缺失使得这个数字更大一些,所以这个数字变大了一些。 +在这里,精度损失使得这个数字稍微大了一些,因此其向上舍入。 -**如果我们希望以正确的方式四舍五入,我们如何使用 `6.35` 为例来解决这个问题?** +**如果我们希望以正确的方式进行舍入,我们应该如何解决 `6.35` 的舍入问题呢?** -在四舍五入之前,我们应该把它接近整数: +在进行舍入前,我们应该使其更接近整数: ```js run alert( (6.35 * 10).toFixed(20) ); // 63.50000000000000000000 ``` -请注意 `63.5` 完全没有精度缺失。这是因为小数部分 `0.5` 实际上是 `1 / 2`。除以2的幂的分数在二进制系统中被精确地表示,现在我们可以围绕它来解决问题: +请注意,`63.5` 完全没有精度损失。这是因为小数部分 `0.5` 实际上是 `1/2`。以 2 的整数次幂为分母的小数在二进制数字系统中可以被精确地表示,现在我们可以对它进行舍入: ```js run alert( Math.round(6.35 * 10) / 10); // 6.35 -> 63.5 -> 64(rounded) -> 6.4 ``` + From 4b05dacef605a23e216523b894aa29b65f24cc8c Mon Sep 17 00:00:00 2001 From: LeviDing Date: Tue, 7 Apr 2020 09:00:43 +0800 Subject: [PATCH 15/25] Update task.md --- .../02-number/3-repeat-until-number/task.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/1-js/05-data-types/02-number/3-repeat-until-number/task.md b/1-js/05-data-types/02-number/3-repeat-until-number/task.md index 1ea3e3d33e..1eef20d165 100644 --- a/1-js/05-data-types/02-number/3-repeat-until-number/task.md +++ b/1-js/05-data-types/02-number/3-repeat-until-number/task.md @@ -2,12 +2,13 @@ importance: 5 --- -# 重复检测,直到输入是一个数字 +# 重复,直到输入的是一个数字 -创建一个函数 `readNumber`,它提示输入一个数字,直到访问者输入一个有效的数字。 +创建一个函数 `readNumber`,它提示输入一个数字,直到访问者输入一个有效的数字为止。 -结果值必须作为数字返回。 +结果值必须以数字形式返回。 -访问者也可以通过输入空行或按“取消”来停止该过程。在这种情况下,函数应该返回 `null`。 +访问者也可以通过输入空行或点击“取消”来停止该过程。在这种情况下,函数应该返回 `null`。 [demo] + From 83fae2c83e843388cd80e5086540078a6b5dff7c Mon Sep 17 00:00:00 2001 From: LeviDing Date: Tue, 7 Apr 2020 09:05:48 +0800 Subject: [PATCH 16/25] Update solution.md --- .../02-number/3-repeat-until-number/solution.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/1-js/05-data-types/02-number/3-repeat-until-number/solution.md b/1-js/05-data-types/02-number/3-repeat-until-number/solution.md index 30c000b3b0..ef65631cc3 100644 --- a/1-js/05-data-types/02-number/3-repeat-until-number/solution.md +++ b/1-js/05-data-types/02-number/3-repeat-until-number/solution.md @@ -15,8 +15,9 @@ function readNumber() { alert(`Read: ${readNumber()}`); ``` -该解决方案有点复杂,可能是因为我们需要处理 null/空行。 +该解决方案有点复杂,因为我们需要处理 `null` 和空行。 -所以我们实际上接受输入,直到它成为“常规数字”。null(取消)和空行都适合该条件,因为在数字形式中它们是 `0`。 +所以,我们实际上接受输入,直到输入的是一个“常规数字”。`null`(取消)和空行都符合该条件,因为在数字形式中它们是 `0`。 + +在我们停止之后,我们需要专门处理 `null` 和空行(返回 `null`),因为将它们转换为数字将返回 `0`。 -在我们停止之后,我们需要专门处理 null 和空行(返回 null),因为将它们转换为数字将返回 `0`。 From 4c076f5ea4c49b736a1a74196665d55408be925a Mon Sep 17 00:00:00 2001 From: LeviDing Date: Tue, 7 Apr 2020 09:11:52 +0800 Subject: [PATCH 17/25] Update task.md --- 1-js/05-data-types/02-number/4-endless-loop-error/task.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/1-js/05-data-types/02-number/4-endless-loop-error/task.md b/1-js/05-data-types/02-number/4-endless-loop-error/task.md index 930efd2e41..b56f782d82 100644 --- a/1-js/05-data-types/02-number/4-endless-loop-error/task.md +++ b/1-js/05-data-types/02-number/4-endless-loop-error/task.md @@ -4,7 +4,7 @@ importance: 4 # 一个偶发的无限循环 -这个循环是无限的。它永远不会结束。为什么? +这是一个无限循环。它永远不会结束。为什么? ```js let i = 0; From 3c36eb41278fe8a80687f4e13cd9de3ce6cee1e5 Mon Sep 17 00:00:00 2001 From: LeviDing Date: Tue, 7 Apr 2020 09:18:53 +0800 Subject: [PATCH 18/25] Update article.md --- 2-ui/1-document/11-coordinates/article.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/2-ui/1-document/11-coordinates/article.md b/2-ui/1-document/11-coordinates/article.md index c363921782..40c42a042f 100644 --- a/2-ui/1-document/11-coordinates/article.md +++ b/2-ui/1-document/11-coordinates/article.md @@ -69,7 +69,7 @@ right:${r.right} 请注意: -- 坐标可能是小数,例如 `10.5`。这是正常的,浏览器内部使用分数进行计算。在设置 `style.left/top` 时,我们不是必须对它们进行舍入。 +- 坐标可能是小数,例如 `10.5`。这是正常的,浏览器内部使用小数进行计算。在设置 `style.left/top` 时,我们不是必须对它们进行舍入。 - 坐标可能是负数。例如滚动页面,使 `elem` 现在位于窗口的上方,则 `elem.getBoundingClientRect().top` 为负数。 ```smart header="为什么需要派生(derived)属性?如果有了 `x/y`,为什么还要还会存在 `top/left`?" From 053f8e6d541297f9cd777c2981eae60a3a4a4814 Mon Sep 17 00:00:00 2001 From: LeviDing Date: Tue, 7 Apr 2020 09:21:52 +0800 Subject: [PATCH 19/25] Update article.md --- 1-js/05-data-types/02-number/article.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/1-js/05-data-types/02-number/article.md b/1-js/05-data-types/02-number/article.md index e1cb711027..f13aa870b1 100644 --- a/1-js/05-data-types/02-number/article.md +++ b/1-js/05-data-types/02-number/article.md @@ -256,7 +256,7 @@ alert( (0.28 * 100 + 0.14 * 100) / 100); // 0.4200000000000001 因此,乘/除法可以减少误差,但不能完全消除误差。 -有时候我们可以尝试完全避免分数。例如,我们正在创建一个电子购物网站,那么我们可以用角而不是元来存储价格。但是,如果我们要打 30% 的折扣呢?实际上,完全避免分数处理几乎是不可能的。只需要在必要时剪掉其“尾巴”来对其进行舍入即可。 +有时候我们可以尝试完全避免小数。例如,我们正在创建一个电子购物网站,那么我们可以用角而不是元来存储价格。但是,如果我们要打 30% 的折扣呢?实际上,完全避免小数处理几乎是不可能的。只需要在必要时剪掉其“尾巴”来对其进行舍入即可。 ````smart header="有趣的事儿" 尝试运行下面这段代码: @@ -425,10 +425,10 @@ JavaScript 有一个内建的 [Math](https://developer.mozilla.org/en/docs/Web/J - 使用 `parseInt/parseFloat` 进行“软”转换,它从字符串中读取数字,然后返回在发生 error 前可以读取到的值。 -分数: +小数: - 使用 `Math.floor`,`Math.ceil`,`Math.trunc`,`Math.round` 或 `num.toFixed(precision)` 进行舍入。 -- 请确保记住使用分数时会损失精度。 +- 请确保记住使用小数时会损失精度。 更多数学函数: From 501f2c7fd65c0e070331ca2b8ef85a5458ed469b Mon Sep 17 00:00:00 2001 From: LeviDing Date: Tue, 7 Apr 2020 09:23:30 +0800 Subject: [PATCH 20/25] Update solution.md --- .../02-number/4-endless-loop-error/solution.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/1-js/05-data-types/02-number/4-endless-loop-error/solution.md b/1-js/05-data-types/02-number/4-endless-loop-error/solution.md index 16201a3458..163b0a2736 100644 --- a/1-js/05-data-types/02-number/4-endless-loop-error/solution.md +++ b/1-js/05-data-types/02-number/4-endless-loop-error/solution.md @@ -1,6 +1,6 @@ 那是因为 `i` 永远不会等于 `10`。 -运行它以查看 `i` 的实际值: +运行下面这段代码来查看 `i` 的 **实际** 值: ```js run let i = 0; @@ -10,8 +10,8 @@ while (i < 11) { } ``` -他们中没有一个完全是 `10`。 +它们中没有一个恰好是 `10`。 -发生这样的事情是因为在添加像 `0.2` 这样的分数时出现了精度损失。 +之所以发生这种情况,是因为对 `0.2` 这样的小数时进行加法运算时出现了精度损失。 -结论:在处理小数部分时避免相等检查。 +结论:在处理小数时避免相等性检查。 From 4a11e4f1a1daaa0b30322f65dfeedbda5345a3d6 Mon Sep 17 00:00:00 2001 From: LeviDing Date: Tue, 7 Apr 2020 09:28:51 +0800 Subject: [PATCH 21/25] Update task.md --- 1-js/05-data-types/02-number/8-random-min-max/task.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/1-js/05-data-types/02-number/8-random-min-max/task.md b/1-js/05-data-types/02-number/8-random-min-max/task.md index ecfa3447b6..36012dce68 100644 --- a/1-js/05-data-types/02-number/8-random-min-max/task.md +++ b/1-js/05-data-types/02-number/8-random-min-max/task.md @@ -2,13 +2,13 @@ importance: 2 --- -# 从最小到最大的随机数 +# 从 min 到 max 的随机数 -用内置函数Math.random() 创建一个从 0 到 1 的随机值(不包括 1 )。 +内建函数 `Math.random()` 会创建一个在 `0` 到 `1` 之间(不包括 `1`)的随机数。 -编写随机函数(min,max)以生成从最小到最大(不包括最大值)的随机浮点数。 +编写一个 `random(min, max)` 函数,用以生成一个在 `min` 到 `max` 之间的随机浮点数(不包括 `max`))。 -实例: +运行示例: ```js alert( random(1, 5) ); // 1.2345623452 From cc7ded90fabd793c1f7e89535c3b8ec53cd7d330 Mon Sep 17 00:00:00 2001 From: LeviDing Date: Tue, 7 Apr 2020 09:33:29 +0800 Subject: [PATCH 22/25] Update solution.md --- 1-js/05-data-types/02-number/8-random-min-max/solution.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/1-js/05-data-types/02-number/8-random-min-max/solution.md b/1-js/05-data-types/02-number/8-random-min-max/solution.md index 562be1f62f..c0c59d3ce4 100644 --- a/1-js/05-data-types/02-number/8-random-min-max/solution.md +++ b/1-js/05-data-types/02-number/8-random-min-max/solution.md @@ -1,9 +1,9 @@ -我们需要将区间 0..1 中的所有值“映射”为从最小值到最大值。 +我们需要将区间 0..1 中的所有值“映射”为范围在 `min` 到 `max` 中的值。 这可以分两个阶段完成: -1. 如果我们将 0..1 的随机数乘以 `max-min`,则可能值的间隔从 0..1 增加到 `0..max-min`。 -2. 现在,如果我们添加 `min`,则可能的间隔将从 `min` 变为 `max`。 +1. 如果我们将 0..1 的随机数乘以 `max-min`,则随机数的范围将从 0..1 增加到 `0..max-min`。 +2. 现在,如果我们将随机数与 `min` 相加,则随机数的范围将为 `min` 到 `max`。 函数实现: @@ -16,3 +16,4 @@ alert( random(1, 5) ); alert( random(1, 5) ); alert( random(1, 5) ); ``` + From f539e0d261111954d7f992a1036f608bd6ccdc14 Mon Sep 17 00:00:00 2001 From: LeviDing Date: Tue, 7 Apr 2020 09:37:59 +0800 Subject: [PATCH 23/25] Update task.md --- .../02-number/9-random-int-min-max/task.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/1-js/05-data-types/02-number/9-random-int-min-max/task.md b/1-js/05-data-types/02-number/9-random-int-min-max/task.md index 8ae2b30676..23053e3d4c 100644 --- a/1-js/05-data-types/02-number/9-random-int-min-max/task.md +++ b/1-js/05-data-types/02-number/9-random-int-min-max/task.md @@ -2,19 +2,19 @@ importance: 2 --- -# 从最小到最大的随机整数 +# 从 min 到 max 的随机整数 -创建一个函数 `randomInteger(min,max)`,该函数从 `min` 到 `max` 生成随机整数,包括 `min` 和 `max` 作为可能值。 +创建一个函数 `randomInteger(min,max)`,该函数会生成一个范围在 `min` 到 `max` 中的随机整数,包括 `min` 和 `max`。 -来自间隔 `min..max` 的任何数字必须以相同的概率出现。 +在 `min..max` 范围中的所有数字的出现概率必须相同。 -功能示例: +运行示例: ```js -alert( random(1, 5) ); // 1 -alert( random(1, 5) ); // 3 -alert( random(1, 5) ); // 5 +alert( randomInteger(1, 5) ); // 1 +alert( randomInteger(1, 5) ); // 3 +alert( randomInteger(1, 5) ); // 5 ``` -您可以使用[上一个任务](info:task/random-min-max)的解决方案作为基础。 +你可以使用 [上一个任务](info:task/random-min-max) 的解决方案作为基础。 From 9699e92336793ad9a5fd72a93582cfbb5bc1863f Mon Sep 17 00:00:00 2001 From: LeviDing Date: Tue, 7 Apr 2020 09:42:36 +0800 Subject: [PATCH 24/25] Update article.md --- 1-js/05-data-types/02-number/article.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/1-js/05-data-types/02-number/article.md b/1-js/05-data-types/02-number/article.md index f13aa870b1..863e131c17 100644 --- a/1-js/05-data-types/02-number/article.md +++ b/1-js/05-data-types/02-number/article.md @@ -418,7 +418,7 @@ JavaScript 有一个内建的 [Math](https://developer.mozilla.org/en/docs/Web/J 对于不同的数字系统: - 可以直接在十六进制(`0x`),八进制(`0o`)和二进制(`0b`)系统中写入数字。 -- `parseInt(str,base)` 将字符串 `str` 解析为在给定的 `base` 数字系统中的整数,`2≤base≤36`。 +- `parseInt(str,base)` 将字符串 `str` 解析为在给定的 `base` 数字系统中的整数,`2 ≤ base ≤ 36`。 - `num.toString(base)` 将数字转换为在给定的 `base` 数字系统中的字符串。 要将 `12pt` 和 `100px` 之类的值转换为数字: From 59974412d501b352d2300df9c2b30b3969cbbe84 Mon Sep 17 00:00:00 2001 From: LeviDing Date: Tue, 7 Apr 2020 09:44:18 +0800 Subject: [PATCH 25/25] Update solution.md --- .../02-number/9-random-int-min-max/solution.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/1-js/05-data-types/02-number/9-random-int-min-max/solution.md b/1-js/05-data-types/02-number/9-random-int-min-max/solution.md index b9c7a095e0..309378857b 100644 --- a/1-js/05-data-types/02-number/9-random-int-min-max/solution.md +++ b/1-js/05-data-types/02-number/9-random-int-min-max/solution.md @@ -1,6 +1,6 @@ # 简单但错误的解决方案 -最简单但错误的解决方案是从 `min` 到 `max` 生成一个值并取它四舍五入的值: +最简单但错误的解决方案是生成一个范围在 `min` 到 `max` 的值,并取对其进行四舍五入后的值: ```js run function randomInteger(min, max) { @@ -11,11 +11,11 @@ function randomInteger(min, max) { alert( randomInteger(1, 3) ); ``` -这个函数是能起作用的,但不正确。获得边缘值 `min` 和 `max` 的概率是其他值的两倍。 +这个函数是能起作用的,但不正确。获得边缘值 `min` 和 `max` 的概率比其他值低两倍。 -如果你多次运行这个例子,你会很容易看到 `2` 出现的频率最高。 +如果你将上面这个例子运行多次,你会很容易看到 `2` 出现的频率最高。 -发生这种情况是因为 `Math.round()` 从间隔 `1..3` 获得随机数并按如下所示进行四舍五入: +发生这种情况是因为 `Math.round()` 从范围 `1..3` 中获得随机数,并按如下所示进行四舍五入: ```js no-beautify values from 1 ... to 1.4999999999 become 1 @@ -27,12 +27,12 @@ values from 2.5 ... to 2.9999999999 become 3 # 正确的解决方案 -这项任务有很多正确的解决方案。其中之一是调整间隔边界。为了确保相同的时间间隔,我们可以生成从 0.5 到 3.5 的值,从而将所需的概率添加到边缘: +这个题目有很多正确的解决方案。其中之一是调整取值范围的边界。为了确保相同的取值范围,我们可以生成从 0.5 到 3.5 的值,从而将所需的概率添加到取值范围的边界: ```js run *!* function randomInteger(min, max) { - // now rand is from (min-0.5) to (max+0.5) + // 现在范围是从 (min-0.5) 到 (max+0.5) let rand = min - 0.5 + Math.random() * (max - min + 1); return Math.round(rand); } @@ -41,7 +41,7 @@ function randomInteger(min, max) { alert( randomInteger(1, 3) ); ``` -另一种方法是使用 `Math.floor` 作为从 `min` 到 `max+1` 的随机数: +另一种方法是使用 `Math.floor` 来取范围从 `min` 到 `max+1` 的随机数: ```js run *!* @@ -63,4 +63,4 @@ values from 2 ... to 2.9999999999 become 2 values from 3 ... to 3.9999999999 become 3 ``` -所有间隔的长度相同,所以最终能够均匀分配。所有整数出现的概率都相同了。 +所有间隔的长度相同,从而使最终能够均匀分配。