「前端每日一问(62)」如何只截取一个数值的整数部分

683 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第27天,点击查看活动详情

本题难度:⭐

本题类型:JavaScript

答:要取一个数值的整数部分,可以使用下面这几种方式:

  • parseInt
  • Math.trunc
  • | 操作符

讲解

不知道大家在日常开发中有没有遇到过类似的需求,对一个数字取整,但不是四舍五入,而是只取整数的部分,比如:

let num = 5.1  // 取整之后为 5
let num = 4.9  // 取整之后为 4
let num = 1.2  // 取整之后为 1
let num = -1.2 // 取整之后为 -1

这个时候,使用 Math.floor 或者 Math.ceil 都不符合需求了,因为要考虑负数的情况:

Math.floor(0.9) // 输出 0 ✔️
Math.floor(-0.9) // 输出-1,不满足需求 ❌

Math.ceil(-0.9) // 输出 -0 ✔️
Math.ceil(0.9)  // 输出1,不满足需求 ❌

遇到这个需求,你会怎么做呢?

parseInt

其实很简单,parseInt 就可以解决

parseInt(0.9)  // 输出 0  ✔️
parseInt(-0.9) // 输出 -0 ✔️
parseInt(1.2)  // 输出 1  ✔️
parseInt(1.6)  // 输出 1  ✔️

Math.trunc

ES6 新增的 API Math.trunc() 也可以解决,这个 API 就是用来解决这个问题的。

Math.trunc(0.9)  // 输出 0  ✔️
Math.trunc(-0.9) // 输出 -0 ✔️
Math.trunc(1.2)  // 输出 1  ✔️
Math.trunc(1.6)  // 输出 1  ✔️

使用位运算符符 | 进行取整

还有一种骚操作,使用位运算符 |

console.log(0.9 | 0)  // 输出 0  ✔️
console.log(-0.9 | 0) // 输出 0 ✔️
console.log(1.2 | 0)  // 输出 1  ✔️
console.log(1.6 | 0)  // 输出 1  ✔️

我也是今天才知道有这种操作,当我尝试去分析它的原理,发现分析不动,后面去查了 ecma262 文档才知道的原因,文档地址

image.png

规范定义,因为 | 操作符,会把左右两边的数字进行 ToInt32 的转换,一般情况ToInt32 的转换就是舍弃小数位。

image.png

翻译一下:设 int 为数学值,其符号为数字的符号,其大小为 floor(abs(ℝ(number)),也就是先求绝对值,再求 Math.floor,当然会带上符号。

所以对自己本身做 | 运算,也是一样的结果,因为 | 操作符,会把左右两边的数字都进行 ToInt32 的转换:

console.log(0.9 | 0.9)  // 输出 0  ✔️
console.log(-0.9 | -0.9) // 输出 0 ✔️
console.log(1.2 | 1.2)  // 输出 1  ✔️
console.log(1.6 | 1.6)  // 输出 1  ✔️

文档里也提出了,这样会有隐患,最多只能截取 31 位的数值,而 javaScript 有效整数范围是 53 位。

image.png

如果大于等于 31 位的数值,数据就会出问题。

image.png

不过我们平时开发要处理的数据一般不会这么大,只要知道这个隐患,控制好范围,还是可以在工作场景中使用这个操作,不过使用的时候最好注释一下,因为一起协作的同事可能不知道这个小技巧。

结尾

阿林水平有限,文中如果有错误或表达不当的地方,非常欢迎在评论区指出,感谢~

如果我的文章对你有帮助,你的👍就是对我的最大支持^_^

我是阿林,输出洞见技术,再会!

上一篇:

「前端每日一问(61)」移动零

下一篇:

「前端每日一问(63)」长度最小的子数组