如何实现一个parseInt
如何实现一个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)
如何实现一个parseInt的更多相关文章
- javascript随机数发现的一个parseInt函数的问题
前几天想伪造一些数据,用到了随机数,没有自己写,便在网上找了一下,找到了这篇文章:https://www.cnblogs.com/starof/p/4988516.html .之后测试了一下,发现了一 ...
- parseInt第二个参数详解
前阵子在stackOverflow上看到两个这样的问题: 为什么parseInt(8,3) == NaN,parseInt(16,3) == 1? 为什么parseInt('dsff66',16) = ...
- 【JS】温故知新: 从parseInt开始
工作中,几乎习惯了大量使用方便的工具库(如underscore.lodash),但是长期的依赖,却有可能在我们注意不到的地方出现黑天鹅,笔者最近就碰到了这样一件例子: parseInt(9e-10); ...
- JS---封装缓动(变速)动画函数---增加任意一个属性
封装缓动(变速)动画---增加任意一个属性 1. 本来的变速动画函数,是获取特定的属性(之前案例是向右移动,所以获取的是left属性) 2. 现在改变为,获取任意一个属性,使其移动到指定的target ...
- JS实现别踩白块小游戏
最近有朋友找我用JS帮忙仿做一个别踩白块的小游戏程序,但他给的源代码较麻烦,而且没有注释,理解起来很无力,我就以自己的想法自己做了这个小游戏,主要是应用JS对DOM和数组的操作. 程序思路:如图:将游 ...
- Java api 入门教程 之 JAVA的包装类
Java语言是一个面向对象的语言,但是Java中的基本数据类型却是不面向对象的,这在实际使用时存在很多的不便,为了解决这个不足,在设计类时为每个基本数据类型设计了一个对应的类进行代表,这样八个和基本数 ...
- java基本数据类型包装类
Java语言是一个面向对象的语言,但是Java中的基本数据类型却是不面向对象的,这在实际使用时存在很多的不便,为了解决这个不足,在设计类时为每个基本数据类型设计了一个对应的类进行代表,这样八个和基本数 ...
- JAVA的包装类 【转】
Java语言是一个面向对象的语言,但是Java中的基本数据类型却是不面向对象的,这在实际使用时存在很多的不便,为了解决这个不足,在设计类时为每个基本数据类型设计了一个对应的类进行代表,这样八个和基本数 ...
- java的包装类(转)
Java语言是一个面向对象的语言,但是Java中的基本数据类型却是不面向对象的,这在实际使用时存在很多的不便,为了解决这个不足,在设计类时为每个基本数据类型设计了一个对应的类进行代表,这样八个和基本数 ...
- java 它 引用(基本类型的包装,构造函数和析构函数c++不同)
一个:java 和c++参考控制 他提到引用,我们会想到java它不喜欢c++里面的指针.当然java内引用和c++里面的引用是不同的. 比如: 比方C++中,我对某一个函数的声明.int a(i ...
随机推荐
- 1-python中的两大法宝和加载数据
python中的两大法宝和加载数据 1. Python两大法宝 ① Python3.6.3相当于一个package,package里面有不同的区域,不同的区域有不同的工具. ② Python语法有两大 ...
- 一文读懂HyperWorks有限元分析流程
(1)通过模型浏览器(Model Browser)或者材料类型(material)图标进行材料模型的创建. (2)通过模型浏览器或者单元类型(property)图标,进行单元类型的创建.必要时,在单元 ...
- Vue 结合Sortablejs实现table行排序
场景 在一个列表展示页面上,使用了表格组件,原有组件本身不支持拖拽功能,需求要求在列表的基础上支持行拖拽排序.因此引入了Sortablejs插件. 问题及解决方案 引入Sortablejs后刚开始都很 ...
- 在.Net Core类库中引入System.Windows.Forms,报错问题
https://blog.rayfalling.com/2020/04/%e5%9c%a8-net-core%e4%b8%ad%e5%bc%95%e5%85%a5system-windows-form ...
- 样本量的确定与OC函数
在之前的假设检验文章中我们说过,在样本量固定的情况下,第一类错误的减少必然会导致第二类错误的增加.按照之前的例子,原假设依旧是一家馒头店每天卖出100个馒头,现在如果减少第一类错误(也就是减少显著性水 ...
- vite vue3 全局批量注册组件
方式1-使用import.meta.glob 同webpack的 require.context一样,这个是vite提供的一个方法 import { createApp, defineAsyncCom ...
- 用commitlint规范团队的git提交信息
前言在一个团队中,每个人的git的commit信息都不一样,五花八门,没有一个机制很难保证规范化,如何才能规范化呢?可能你想到的是git的hook机制,去写shell脚本去实现.这当然可以,其实Jav ...
- A - Ability Draft Gym - 102155A 状压DP
传送门 题意:有两个队伍,每队有n个人,每个人可以有s个普通技能和一个特殊技能.现在可以按照顺序抽技能卡,问各自都在最优策略下双方队伍的技能总分最大差值. 思路:算是一道看着简单但思路形成比较麻烦的一 ...
- emplace_back VS push_back
简介 一直说, emplace_back 比 push_back 快, 我不信, 哈哈~~ 参考链接 https://blog.csdn.net/yockie/article/details/5267 ...
- JsonConvert反序列化枚举转换
适用场景:反序列化对象里面存在枚举类型 说明 在使用JsonConvert.DeserializeObject转换对象的时候,想要更直观的看到值对应的含义,一般会设定一个枚举值,但是在转换的时候,由于 ...