Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

百度:手写parseInt的实现,要求简单一些,把字符串型的数字转化为真正的数字即可,但不能使用JS原生的字符串转数字的API,比如Number() #89

Open
sisterAn opened this issue Jul 28, 2020 · 2 comments
Labels

Comments

@sisterAn
Copy link
Owner

sisterAn commented Jul 28, 2020

返回解析后的整数值。 如果被解析参数的第一个字符无法被转化成数值类型,则返回 NaN

注意:radix 参数为 n 将会把第一个参数看作是一个数的 n 进制表示,而返回的值则是十进制的。例如:

parseInt('123', 5) // 将'123'看作5进制数,返回十进制数38 => 3*5^0 + 2*5^1 + 1*5^2  = 38

以下 2 进制没有问题

function _parseInt(str, radix) {
    let str_type = typeof str;
    let res = 0;
    if (str_type !== 'string' && str_type !== 'number') {
        // 如果类型不是 string 或 number 类型返回NaN
        return NaN
    }

    // 字符串处理
    str = String(str).trim().split('.')[0]
    let length = str.length;
    if (!length) {
        // 如果为空则返回 NaN
        return NaN
    }

    if (!radix) {
        // 如果 radix 为0 null undefined
        // 则转化为 10
        radix = 10;
    }
    if (typeof radix !== 'number' || radix < 2 || radix > 36) {
        return NaN
    }

    for (let i = 0; i < length; i++) {
        let arr = str.split('').reverse().join('');
        res += Math.floor(arr[i]) * Math.pow(radix, i)
    }

    return res;
}

考虑 16 进制,完整版如下

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)
}
@dlrandy
Copy link

dlrandy commented Sep 28, 2021

const regex = /^(?[+|-]*)(?[0]?[Xx]?)(?[0-9a-fA-F]+)/ 这里是什么原因不用问号?
const regex = /^(?[+|-]?)(?[0]?[Xx]?)(?[0-9a-fA-F]+)/

@xllpiupiu
Copy link

//可以传两个参数  parsenInt('123',5)将'123'看作5进制 返回10进制
function _parseInt2(str, radix) {
    //1. 对入参做判断
    let strType = typeof str
    if (strType !== 'string' && strType !== 'number') return NaN
    if (typeof radix !== 'number' || radix < 2 || radix > 36) return NaN
    //2. 对str做处理 只取整数部分
    let strHandle = String(str).trim().split('.')[0]
    console.log('strHandle: ', strHandle);
    if (strHandle.length === 0) return NaN
    //3. radix处理
    if (!radix) radix = 10
    //4. 转换逻辑  将字符反转
    let strReverse = strHandle.split('').reverse().join('')
    console.log('strReverse: ', strReverse);
    let res = 0
    for (let i = 0, len = strReverse.length; i < len; i++) {
        if (strReverse[i] >= radix) return NaN
        res += strReverse[i] * Math.pow(radix, i)
    }
    return res
}
console.log(_parseInt2('123', 5))

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants