经典问题,定长二进制数计算会有溢出的问题,为了解决这个问题可以用 string 来表示数字,并在这样的字符串构造上实现加法过程,已实现,效果如下所示:(已经挂到 window.bigIntAdd 了)
输入 a:
输入 b:
a + b = ## a 是无效输入 (请输入正整数) ##
注意到:
- '0' + '1' === '1'
- '11' + '2' === '10' + ('1' + '2') === '13'
- '29' + '3' === '20' + ('9' + '3') === ('20' + 进位1) + '2' === 22
可以看到第三步的进位处理是一种从低位到高位不断进位的递推关系,因此有:
00function addDecimal(a: string, b: string) { 01 return Number(a) + Number(b) 02} 03 04export function bigIntAdd(a: string, b: string): string { 05 const lastA = a[a.length - 1] 06 const lastB = b[b.length - 1] 07 08 if (typeof lastA === 'undefined') return b 09 if (typeof lastB === 'undefined') return a 10 11 const res = addDecimal(lastA, lastB) 12 const carry = res >= 10 ? '1' : '0' 13 14 // 将进位 carry 加到 half 上就好了 15 const half = bigIntAdd(a.slice(0, -1), b.slice(0, -1)) 16 const full = bigIntAdd(half, carry) 17 18 // 0 开头就不输出 full 了 19 if (full === '0') return (res % 10).toString() 20 21 return full + (res % 10).toString() 22} 23 24console.group('bigIntAdd') 25 console.time('bigIntAdd') 26 console.log(bigIntAdd('0', '0')) 27 console.log(bigIntAdd('4', '0')) 28 console.log(bigIntAdd('1', '8')) 29 console.log(bigIntAdd('9', '11')) 30 console.log(bigIntAdd('88', '12')) 31 console.log(bigIntAdd('99', '999999')) 32 console.log(bigIntAdd('99999999999', '99999')) 33 console.log(bigIntAdd('2', '9'.repeat(999))) 34 console.timeEnd('bigIntAdd') 35console.groupEnd()