3

VLQ & Base64 VLQ 编码方式的原理及代码实现 - Echoyya、

 1 year ago
source link: https://www.cnblogs.com/echoyya/p/16726545.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

VLQ & Base64 VLQ 编码方式的原理及代码实现

VLQ (Variable-length quantity)是一种通用的,使用任意位数的二进制来表示一个任意大的数字的一种编码方式。

编码实现: ** 对数字137进行VLQ**编码,以下为分解步骤:

  1. 将137转成二进制形式 —— 10001001
  2. 七位一组做分组,不足的补前导0 —— 0000001 0001001
  3. 最后一组开头补0,其余补1(1表示连续位) —— 10000001 00001001.
  4. 最终137的VLQ编码形式为 —— 10000001 00001001
// 1. 将137转成二进制形式 —— 10001001
let binary = (137).toString(2);
// 2. 七位一组做分组,不足的补前导0 —— 0000001 0001001
let padded = binary.padStart(Math.ceil(binary.length / 7) * 7, '0');
// 3. 最后一组开头补0,其余补1(1表示连续位) —— 10000001 00001001
let groups = padded.match(/[01]{7}/g);
groups = groups.map((item, index) => (index == groups.length - 1 ? '0' : '1') + item);
let vlqCode = groups.join('');
// 4 最终137的VLQ编码形式为 —— 10000001 00001001
console.log(vlqCode);

Base64 VLQ

  • Base64 是一种可以把二进制数据编码成用 ASCII 表示的一种编码规则,Base64 VLQ 需要能够表示负数, 于是规定了需要先把数字变成无符号数, 用最后一位来作为符号标志位。
  • 一个Base64字符只能表示6bit(2^6)的数据,而第一位表示连续位,Base64 VLQ需要能够表示负数,因此最后一位用作符合标志位,真正表示数字的只有中间4位,因此一个单元表示的范围是[-15,15],如果超过了就要用连续位了
  • 在Base64 VLQ中,编码顺序是从低位到高位,而在VLQ中,编码顺序是从高位到低位
  • 常见用于项目中sourceMap编码

编码实现: ** 对数字137进行Base64 VLQ**编码,以下为分解步骤:

  1. 将137转成二进制形式 10001001,如果是负数需要转成绝对值 Math.abs
  2. 137是正数,末位符号位补0, 100010010 正数末位补0,负数末位补1
  3. 五位一组做分组,不足的补0, 01000 10010
  4. 将数组倒序排序 [ '10010', '01000' ] ,低位在前,高位在后
  5. 最后一组开头补0,其余补1(1表示连续位),110010 001000
  6. 转成base64,最终137的Base64 VLQ编码形式为 —— yI
let base64 = [
    'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
    'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
    'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
    'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
];

function encode(num) {
    // 1. 将137转成二进制形式  10001001,如果是负数需要转成绝对值 
    let binary = (Math.abs(num)).toString(2);
    // 2. 137是正数,末位符号位补0, 100010010 正数末位补0,负数末位补1
    binary += num >= 0 ? '0' : '1';
    // 3. 五位一组做分组,不足的补0, 01000 10010
    binary = binary.padStart(Math.ceil(binary.length / 5) * 5, '0');
    // 4. 将数组倒序排序 [ '10010', '01000' ] 低位在前,高位在后
    let parts = binary.match(/\d{5}/g);
    parts.reverse(); 
    // 5. 最后一组开头补0,其余补1, 110010 001000 6个位bit
    parts = parts.map((item, index) => (index == parts.length - 1 ? '0' : '1') + item);
    // 6. 转成base64
    let chars = [];
    for (let i = 0; i < parts.length; i++) {
        let base64Index = parseInt(parts[i], 2);
        chars.push(base64[base64Index]);
    }
    return chars.join('');
}
let result = encode(137); // yI

在线编码解码的网站:http://murzwin.com/base64vlq.html


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK