如何实现一个parseInt
程序员文章站
2022-04-03 21:55:28
如何实现一个parseInt 如果string不为字符串类型, 则先将string转化为字符串类型 string会忽略前后的空白 依次解析字符, 如果字符不是指定基数中的字符( 例如:2进制中的3、 10进制中的'f' )则停止解析( 首字符为'+'或' '时除外 ), 返回已经解析好的整数 如果无 ......
如何实现一个parseint
function(string, [radix]) {}
- 如果string不为字符串类型, 则先将string转化为字符串类型
- string会忽略前后的空白
- 依次解析字符, 如果字符不是指定基数中的字符( 例如:2进制中的3、 10进制中的'f' )则停止解析( 首字符为'+'或'-'时除外 ), 返回已经解析好的整数
- 如果无法解析为整数, 则返回nan
- radix 默认值不为10, 在radix为undefined、0或者没有指定时, 做以下处理
- 如果string以'0x'或'0x'开头时, 基数为16
- 如果string以'0'开头时, 基数为8或者10(每个浏览器的具体实现不同, es5规定此时为10)
- 如果string以其他任何字符开头时, 基数为10
- radix的范围为2-36
不考虑进制radix
代码实现
const _parseint = (str, radix) => { if (typeof str !== 'string') str = string(str) str = str.trim() const regex = /^(?<fuhao>[\+|\-]*)(?<num>\d+)/ if (!regex.test(str)) return nan const groups = str.match(regex).groups radix = 10 const arr = groups.num.split('') const len = arr.length let result = 0 for(let i = 0; i < len; i++) { const num = arr[i] * math.pow(10, len - i - 1) if (isnan(num)) break else result += num } return result * (groups.fuhao === '-' ? -1 : 1) }
测试用例
const assert = require('assert') assert.strictequal(_parseint(null), nan) assert.strictequal(_parseint('0e0'), 0) assert.strictequal(_parseint('08'), 8) assert.strictequal(_parseint(0.0000003), 3) assert.strictequal(_parseint(0.00003), 0) assert.strictequal(_parseint(-0.0000003), -3) assert.strictequal(_parseint('6.022e23'), 6) assert.strictequal(_parseint(6.022e2), 602)
考虑radix
代码实现
const _parseint = (str, radix) => { // 不为string类型先转化为string 类型 if (typeof str !== 'string') str = string(str) // 删除首尾空白 str = str.trim() // 正则匹配[+|-]?[0]?[xx]?[0-9a-fa-f]+ const regex = /^(?<fuhao>[\+|\-]*)(?<radix>[0]?[xx]?)(?<num>[0-9a-fa-f]+)/ // 无法匹配返回nan if (!regex.test(str)) return nan // 匹配出符号、进制、数字三个分组 const groups = str.match(regex).groups // radix的有效范围为 2-36 if (radix && (radix < 2 || radix > 36)) return nan // 如果没有指定radix, radix 会有以下默认值 if (!radix) { if (groups.radix.touppercase() === '0x') radix = 16 else if (groups.radix === '0') radix = 8 else radix = 10 } // 挨个字符串解析,如果遇到无法解析时则停止解析,返回已经解析好的整数 let splitarr = groups.num.split('') const arr = [] for(let i = 0; i < splitarr.length; i++) { // 根据charcode来做转行为实际数据, 0-9为[48-57],a-f为[65-70] const charcode = splitarr[i].touppercase().charcodeat() let num // 字符为[a-f]时, 实际数字为charcode -55 if(charcode >= 65) num = charcode - 55 // 字符为[0-9]时, 实际数字为charcode - 48 else num = charcode - 48 // 当实际数字大于radix时, 无法解析则停止字符串遍历 if (num > radix) { break } else { arr.push(num) } } const len = arr.length // 当实际数字数组长度为0时, 返回nan if(!len) return nan let result = 0 // 依次解析实际数字数组, 组合成真正的数字 for(let i = 0; i < len; i++) { const num = arr[i] * math.pow(radix, len - i - 1) result += num } // 算法匹配到的正负号 return result * (groups.fuhao === '-' ? -1 : 1) }
测试用例
const assert = require('assert') // 以下返回15 assert.strictequal(_parseint('0xf', 16), 15) assert.strictequal(_parseint('f', 16), 15) assert.strictequal(_parseint('17', 8), 15) assert.strictequal(_parseint(021, 8), 15) assert.strictequal(_parseint('015', 10), 15) assert.strictequal(_parseint(15.99, 10), 15) assert.strictequal(_parseint('15,123', 10), 15) assert.strictequal(_parseint('fxx123', 16), 15) assert.strictequal(_parseint('1111', 2), 15) assert.strictequal(_parseint('15 * 3', 10), 15) assert.strictequal(_parseint('15e2', 10), 15) assert.strictequal(_parseint('15px', 10), 15) assert.strictequal(_parseint('12', 13), 15) // 以下返回nan assert.strictequal(_parseint('hello', 8), nan) assert.strictequal(_parseint('546', 2), nan) // 以下返回-15 assert.strictequal(_parseint('-f', 16), -15) assert.strictequal(_parseint('-0f', 16), -15) assert.strictequal(_parseint('-0xf', 16), -15) assert.strictequal(_parseint(-15.1, 10), -15) assert.strictequal(_parseint(' -17', 8), -15) assert.strictequal(_parseint(' -15', 10), -15) assert.strictequal(_parseint('-1111', 2), -15) assert.strictequal(_parseint('-15e1', 10), -15) assert.strictequal(_parseint('-12', 13), -15) // 以下返回4 assert.strictequal(_parseint(4.7, 10), 4) assert.strictequal(_parseint(4.7 * 1e22, 10), 4) assert.strictequal(_parseint(0.00000000000434, 10), 4) // 以下返回224 assert.strictequal(_parseint('0e0', 16), 224)