一、简介
Base-x是一个实现不同进制数之间的转换的JavaScript库。它可以将16进制的字符串转换为二进制、八进制、十进制等其他任意进制的字符串。这个库实现的主要思路是利用了JavaScript中的BigInt类型,可以处理更大范围的数字。目前,Base-x支持Base2 ~ Base62的转换。
二、原理
在计算机科学中,base-x就是将数字转换为一个X进制的数字系统。在这个数字系统中,数字0表示第0位,数字1表示第1位,数字2表示第2位,以此类推。我们通常使用的十进制数字系统是将数字分解成10的幂的形式,比如数值203,可以写作210^2 + 010^1 + 3*10^0,其中的10就是十进制。 因此,数字在不同进制数之间的转换,本质上就是要将数字表示成另一种进制数的形式。这里介绍的是将数字转换为字符串的形式。使用Base-x进行转换,需要确定两个参数:要将数字转换成的基数(即进制),和要转换的数字。然后,就可以使用一些特殊的函数将数字转换为目标进制下的字符串。
三、使用方法
1、安装
npm install base-x
2、基本示例
下面是一个简单示例,将一个任意进制的数转换为目标进制的字符串:
const baseX = require('base-x')
const bs16 = baseX('0123456789abcdef') // 创建一个可以转换成16进制的实例,输入字符串中包含了16个字符
const buffer = Buffer.from('hello world')
const str16 = bs16.encode(buffer) // 将buffer对象转换成hex字符串
console.log(str16) // 68656c6c6f20776f726c64
const bytes = bs16.decode(str16) // 将hex字符串转换成buffer对象
console.log(bytes.toString()) // hello world
3、常用API
encode(raw: ArrayLike<byte>): string
将输入的原生数组对象转换成一个字符串,其按照当前对象所定义的进制方式进行转换。这里的byte值会从Base-x实例初始化的时候设置的编码表中查找。
decode(encoded: string): Uint8Array
将给定的字符串解码为一个数字数组,并按照当前对象所定义的进制方式进行解码。这里的数字数组会将byte值从Base-x实例初始化的时候设置的编码表中查找。
4、实现原理
Base-x的实现,主要依赖于下面两个重要的函数:
// 将原生数组转换为BigInt类型的数字
function decodeUnsafe(val: ArrayLike<byte>): bigint {
let res = BigInt(0)
// 从右向左进行遍历
for (let i = 0; i < val.length; i++) {
res = res * BigInt(BASE) + BigInt(val[i])
}
return res
}
// 将BigInt数字转换为字符串
function encode(val: number | bigint | ArrayLike<byte>): string {
if (typeof val === 'number' || typeof val === 'bigint') {
val = Buffer.from(val.toString(16), 'hex')
}
if (isBuffer(val)) return encode.buffer(val)
return fromBigInt(decodeUnsafe(val))
}
在这两个函数中,decodeUnsafe()函数主要实现了将输入的原生数组转换为BigInt类型的数字,同时定义了进制的基数。该函数依靠循环和BigInt类型的运算,将每一位的数字依次拼接起来,最终得到一个BigInt类型的数字表示。 encode()函数则是将BigInt类型的数字再转换回字符串。该函数实现了将BigInt类型的数字拆分成各个位的数字,依次从编码表中查找与之对应的字符,最终得到字符串表示。
参考资料
- Base-x官网:https://github.com/cryptocoinjs/base-x#readme
- Hexadecimal数字系统:https://en.wikipedia.org/wiki/Hexadecimal
- JavaScript中的BigInt类型:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt