parseInt() 不总是正确地转换为整数
在 JavaScript 中,所有的数字都是浮点型的,整数是没有小数的浮点数。将一个数 n
转换为整数意味着找到接近 n
的整数。你可能认为 parseInt()
能处理这项任务,但是它不能。至少,不总是有效。
parseInt() 如何工作
parseInt()
有如下定义:
parseInt(value, radix?)
它将 value
转换为字符串,然后忽略前导空格并找寻尽可能连续的整数位。
关于基数(radix)
默认值为 10,如果 radix
缺省。除非 value
以 ‘0x’ 或 ‘0X’ 开头,这种情况下 radix
的值将默认为 16(十六进制数)。
Number.parseInt('0xA') // 10
如果 radix
已经设定为 16,那十六进制前缀是可选的。
Number.parseInt('0xA', 16) // 10
Number.parseInt('A', 16) // 10
以上我们介绍了 ECMAScript 规范 定义的 parseInt()
行为。另外,一些引擎将以 0 为前缀的整数的 radix
设置为 8:
Number.parseInt('010') // 8
Number.parseInt('0109') // 8 // 忽略位数 ≥ 8
因此,最好总是明确的指定 radix
。
例子
一些例子:
Number.parseInt(' 12', 10) // 12
Number.parseInt('12**', 10) // 12
Number.parseInt('12.34', 10) // 12
Number.parseInt(12.34, 10) // 12
最后一个例子告诉我们可以使用 parseInt()
转换数字为整数。然而,这里有一个转换错误的例子:
Number.parseInt(1000000000000000000000.5, 10) // 1
说明:parseInt
首先将参数转换为字符串。
String(1000000000000000000000.5) // '1e+21'
然后 parseInt
不识别 “e” 为整数位而停止解析 1 后面的内容。另一个例子:
Number.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(Number.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()
行为不同。
扩展阅读
文章由 吳文俊 翻译,原文地址 parseInt() doesn’t always correctly convert to integer,转载请注明来源。