LeetCode 67题题解。
想必经典的模拟加法大家都会,所以看到这题的时候,我就知道一定会有人用BigInt;果然如此。但是那位并没有解释BigInt的相关内容,只是给出了答案,所以这里主要是介绍一下BigInt的内容。先来看写法:
function addBinary(a: string, b: string): string {
return (BigInt("0b" + a) + BigInt("0b" + b)).toString(2);
}
关于这个写法,可能存在三个疑问:
- 为什么要在a、b前面加上一个
0b
? toString
输出是否正常,会不会带上控制台输出时结尾的n?- 兼容性怎么样?
我们也知道,js / ts里的最大安全整数是253 - 1,超出这个范围的整数运算就不再准确(比如著名的2**53 === 2**53 + 1
)或无法表示了。为了解决这个问题,就有了BigInt提案(一开始似乎是叫Integer),并且在ES10中成为规范;这是BigInt的历史背景。也是因为这个原因,BigInt不能和number互操作,必须进行类型转换,而且在转换过程中可能会丢失精度。
关于第一个问题,如果不考虑题目中给的数据范围,其实我们的第一反应应该是用parseInt
:
function addBinary(a: string, b: string): string {
return (parseInt(a, 2) + parseInt(b, 2)).toString(2);
}
在这种情况下,是不需要加上0b
的,因为已经在parseInt
中指定了是二进制。但BigInt的构造函数只有一个参数,所以需要加上这个前缀来表明这是一个代表二进制数的字符串(0B
也行)。
关于第二个问题,因为console.log
是一个非官方规范,每个浏览器有自己的实现,所以控制台输出和toString
方法的输出没有必然联系。而且文档也说明了,BigInt的toString
不会带上结尾的n。有一个很有意思的事,就是BigInt没有-0
;不过跟这个话题没什么关系。
关于第三个问题,这个特性目前还没有稳定,兼容性只有70%多。但是主流浏览器已经兼容,而且也有polyfill,所以兼容性不是一个很大的问题。