Skip to content

Commit b3eec5c

Browse files
authored
Merge pull request ruanyf#575 from picc-lu/picc-lu-patch-1
请求更新——Number.isInteger 和 Math.fround 一节
2 parents 1335934 + efd6a71 commit b3eec5c

File tree

1 file changed

+68
-8
lines changed

1 file changed

+68
-8
lines changed

docs/number.md

Lines changed: 68 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ Number.parseFloat === parseFloat // true
132132

133133
## Number.isInteger()
134134

135-
`Number.isInteger()`用来判断一个值是否为整数。需要注意的是,在 JavaScript 内部,整数和浮点数是同样的储存方法,所以 3 和 3.0 被视为同一个值。
135+
`Number.isInteger()`用来判断一个值是否为整数。需要注意的是,在 JavaScript 内部,整数和浮点数采用的是同样的储存方法,所以 3 和 3.0 被视为同一个值。
136136

137137
```javascript
138138
Number.isInteger(25) // true
@@ -142,6 +142,35 @@ Number.isInteger("15") // false
142142
Number.isInteger(true) // false
143143
```
144144

145+
注意,由于 JavaScript 浮点数采用的是 IEEE 754 标准,表示数值时最多只能存储 53 位二进制位数(1 位隐藏位与 52 位有效位)。超出位数上限时,第 54 位会尝试是否往第 53 位进位(0 不进位,1 进位),它和它往后的位数一概丢弃,这种情况下可能会导致误判。
146+
147+
```javascript
148+
3 === 3 + 2e-16 // true
149+
Number.isInteger(3.0000000000000002) // true
150+
// 3 的二进制 2 位,2e-16 的二进制最多能表示 51 位
151+
// 第 3 ~ 53 位全为 0,直到第 55 位才开始出现 1,而这一位被丢弃了,误判为 true
152+
153+
3 + 4e-16 === 3 + 6e-16 // true
154+
Number.isInteger(3.0000000000000004) // false
155+
Number.isInteger(3.0000000000000006) // false
156+
// 第 51 位已为 1,且不会丢精度,所以 JavaScript 判定此数包含小数,返回 false
157+
```
158+
159+
数值的大小在 -1 与 1 之间(不含两个端点)时,其绝对值小于 `Number.MIN_VALUE` 即视为 0。
160+
161+
```javascript
162+
Number.MIN_VALUE // 5e-324
163+
5e-325 === 0 // true
164+
Number.isInteger(Number.MIN_VALUE) // false
165+
Number.isInteger(5e-325) // true
166+
167+
3e-324 === Number.MIN_VALUE // true
168+
Number.isInteger(3e-324) // false
169+
// 同样由于精度问题,即使是比 Number.MIN_VALUE 略小的数也会被判为 5e-324。
170+
```
171+
172+
因此,在金融、天文等领域的数据精度要求较高、判断值是否整数的情况下,不建议使用`Number.isInteger()`原生函数,请使用包含正则的函数替代。
173+
145174
ES5 可以通过下面的代码,部署`Number.isInteger()`
146175

147176
```javascript
@@ -510,17 +539,48 @@ Math.imul(0x7fffffff, 0x7fffffff) // 1
510539

511540
### Math.fround()
512541

513-
Math.fround 方法返回一个数的单精度浮点数形式。
542+
`Math.fround` 方法返回一个数的单精度浮点数形式。
543+
544+
对于 -2 的 24 次方至 2 的 24 次方(不含两端)的整数,返回结果与参数本身一致。
514545

515546
```javascript
516-
Math.fround(0) // 0
517-
Math.fround(1) // 1
518-
Math.fround(1.337) // 1.3370000123977661
519-
Math.fround(1.5) // 1.5
520-
Math.fround(NaN) // NaN
547+
Math.fround(0) // 0
548+
Math.fround(1)   // 1
549+
Math.fround(2 ** 24 - 1) // 16777215
521550
```
522551

523-
对于整数来说,`Math.fround`方法返回结果不会有任何不同,区别主要是那些无法用 64 个二进制位精确表示的小数。这时,`Math.fround`方法会返回最接近这个小数的单精度浮点数。
552+
单精度浮点数采用 IEEE 754 标准,最多由 24 位二进制位数(1 位隐藏位与 23 位有效位)表达数值,若参数绝对值大于 2 的 24 次方,返回的结果便开始丢失精度。
553+
554+
```javascript
555+
Math.fround(2 ** 24) // 16777216
556+
Math.fround(2 ** 24 + 1) // 16777216
557+
```
558+
559+
`Math.fround` 方法主要将双精度浮点数转为单精度浮点数,第 25 位二进制数尝试往上一位进位,它与它往后的位数全部丢弃。
560+
561+
```javascript
562+
// 未丢失有效精度
563+
Math.fround(1.125) // 1.125
564+
Math.fround(7.25) // 7.25
565+
566+
// 丢失精度
567+
Math.fround(0.3)   // 0.30000001192092896
568+
Math.fround(0.7)   // 0.699999988079071
569+
Math.fround(1.0000000123) // 1
570+
```
571+
572+
对于 `NaN``Infinity`,此方法返回原值。其它类型而言,`Math.fround` 方法会将其转为数值再返回单精度浮点数。
573+
574+
```javascript
575+
Math.fround(NaN) // NaN
576+
Math.fround(Infinity) // Infinity
577+
578+
Math.fround('5') // 5
579+
Math.fround(true) // 1
580+
Math.fround(null) // 0
581+
Math.fround([]) // 0
582+
Math.fround({}) // NaN
583+
```
524584

525585
对于没有部署这个方法的环境,可以用下面的代码模拟。
526586

0 commit comments

Comments
 (0)