parseInt() 不总是正确地转换为整数

parseInt() 不总是正确地转换为整数

在 JavaScript 中,所有的数字都是浮点型的,整数是没有小数的浮点数。将一个数 n 转换为整数意味着找到接近 n 的整数。你可能认为 parseInt() 能处理这项任务,但是它不能。至少,不总是有效。

parseInt() 如何工作

parseInt() 有如下定义:

parseInt(value, radix?)

它将 value 转换为字符串,然后忽略前导空格并找寻尽可能连续的整数位。

关于基数(radix)

默认值为 10,如果 radix 缺省。除非 value 以 '0x' 或 '0X' 开头,这种情况下 radix 的值将默认为 16(十六进制数)。

parseInt('0xA'); // 10

如果 radix 已经设定为 16,那十六进制前缀是可选的。

parseInt('0xA', 16); // 10

parseInt('A', 16); // 10

以上我们介绍了 ECMAScript 规范 定义的 parseInt() 行为。另外,一些引擎将以 0 为前缀的整数的 radix 设置为 8:

parseInt('010'); // 8

parseInt('0109'); // 8 // 忽略位数 ≥ 8

因此,最好总是明确的指定 radix

例子

一些例子:

parseInt('   12', 10); // 12
parseInt('12**', 10); // 12
parseInt('12.34', 10); // 12
parseInt(12.34, 10); // 12

最后一个例子告诉我们可以使用 parseInt() 转换数字为整数。然而,这里有一个转换错误的例子:

parseInt(1000000000000000000000.5, 10); // 1

说明:parseInt 首先将参数转换为字符串。

String(1000000000000000000000.5); // '1e+21'

然后 parseInt 不识别 "e" 为整数位而停止解析 1 后面的内容。另一个例子:

parseInt(0.0000008, 10); // 8

//同理
String(0.0000008); // '8e-7'

这些限制了 parseInt() 的可用性。然而请注意,出现错误的正指数的数开始于 ±1e+21:

String(1e20); // '100000000000000000000'
String(1e21); //'1e+21'

这将远远超出 JavaScript 的整数范围 [−253, 253]

替代 parseInt() 的方法

函数 Math.trunc()toInteger()Math.round() 通常用于 number 类型。 传入这些函数的参数会隐式转换为数字类型,所以:'80w' => NaN,这与 parseInt() 不同。

Math.trunc()

ES6 中添加 Math.trunc() 函数用于截断数字的小数部分:

Math.trunc(80.6); // 80
Math.trunc('80.1'); // 80
Math.trunc('hello'); // NaN
Math.trunc(NaN); // NaN
Math.trunc(undefined); // NaN

关于 Math.trunc() 博客文章 "Javascript 中的数字截断" 的介绍更详细。

toInteger()

一个好的选择是使用下面的方法,toInteger() 操作来执行 ECMAScript 规范:

function toInteger(x) {
  x = Number(x);
  return x < 0 ? Math.ceil(x) : Math.floor(x);
}

这个方法简单地移除小数部分。例如:

toInteger(3.2); // 3
toInteger(3.5); // 3
toInteger(3.8); // 3

toInteger(-3.2); // -3
toInteger(-3.5); // -3
toInteger(-3.8); // -3

Math.round()

博客 "Integers and shift operators in JavaScript" 提到几个转换数字为整数的方法。一个好的选项 Math.round(),其中 Math.round() 总是使用四舍五入的方式获取最近的整数:

Math.round(3.2); // 3
Math.round(3.5); // 4
Math.round(3.8); // 4

Math.round(-3.2); // -3
Math.round(-3.5); // -3
Math.round(-3.8); // -4

4 被认为最接近 3.5,而 -3 被认为最接近 -3.5。这与 parseInt() 行为不同。

扩展阅读

本文作者 Axel Rauschmayer,转载请注明来源链接:

原文链接:https://2ality.com/2013/01/parseint.html

本文链接:https://tie.pub/2019/06/parseint-does-not-always-correctly-convert-to-integer/