Base-x:实现不同进制数之间的转换

发布时间:2023-05-22

一、简介

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类型的数字拆分成各个位的数字,依次从编码表中查找与之对应的字符,最终得到字符串表示。

参考资料