最近想对js中的数字进行压缩, 百度了一下, 发现相关结果很少, 比如:
//var base_symbols = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz~`!@#$%^&*()-_=+[{]}\\\\|;:'",<.>/?????";
var base_symbols = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz~`!@#$%^&*()-_=+[{]}\\|;:'\",<.>/?¿¡";
function baseConvert(src, from_base, to_base, src_symbol_table, dest_symbol_table) {
// From: convert.js: http://rot47.net/_js/convert.js
// Modified by MLM to work with BigInteger: https://github.com/peterolson/BigInteger.js
src_symbol_table = src_symbol_table ? src_symbol_table : base_symbols;
dest_symbol_table = dest_symbol_table ? dest_symbol_table : src_symbol_table;
if(from_base > src_symbol_table.length || to_base > dest_symbol_table.length) {
console.warn("Can't convert", src,"to base", to_base,"greater than symbol table length. src-table:", src_symbol_table.length,"dest-table:", dest_symbol_table.length);
return false;
}
var val = bigInt(0);
for(var i = 0; i < src.length; i ++) {
val = val.multiply(from_base).add(src_symbol_table.indexOf(src.charAt(i)));
}
if(val.lesser(0)) {
return 0;
}
var r = val.mod(to_base);
var res = dest_symbol_table.charAt(r);
var q = val.divide(to_base);
while(!q.equals(0)) {
r = q.mod(to_base);
q = q.divide(to_base);
res = dest_symbol_table.charAt(r) + res;
}
return res;
}
但由于缺少BigInteger.js
支持, 此段代码无法使用. 于是, 结合网友的点子, 一段新的代码诞生了!
十进制转N进制:
if(!diyBase.dftBase) {
/**
* [A-Z]字符集
* @type {string}
*/
diyBase.dftBase = (function(f,t){var i=f,c='';while(i<=t){c+=String.fromCharCode(i++)}return c;})(65,90)
}
/**
* 自定义进制
* @param {number} n 自然数
* @param charset 进制字符集. 默认[A-Z]
* @param hasZero 进制是否含0. 默认不含, 与charset对应
* @example
* // 十六进制
* diyBase(10, '0123456789ABCDEF', true) // return 'A'
* diyBase(255, '0123456789ABCDEF', true) // return 'FF'
* // excel 中的列
* diyBase(25) // return 'Z'
* diyBase(26) // return 'AA'
* @return {string} 返回值
*/
function diyBase(n, charset, hasZero) {
charset = charset||diyBase.dftBase;
hasZero = hasZero!==undefined?!!hasZero:false;
if(n < charset.length){
return charset.substr(n, 1);
}
// 递归个位以上的部分
var high = Math.floor(n / charset.length);
var unit = n % charset.length;
return diyBase(high - (1^hasZero), charset, hasZero) + charset.substr(unit, 1);
}
N进制转十进制:
/**
* @example
* diyBaseDecode('A', '0123456789ABCDEF', true) // returns 10
* diyBaseDecode('FF', '0123456789ABCDEF', true) // returns 255
* diyBaseDecode('Z') // returns 25
* diyBaseDecode('AA') // returns 26
* @param {string} c
* @param {string} charset
* @param {boolean} [hasZero]
* @returns {number}
*/
function diyBaseDecode(c, charset, hasZero) {
charset = charset||diyBase.dftBase;
hasZero = hasZero!==undefined?!!hasZero:false;
var hz = (1^hasZero),cl = charset.length;
var numList = c.split('').reduce(function (p, v, i,a) {
var idx = charset.indexOf(v) + hz, pow = Math.pow(cl, a.length - 1 - i);
p[i] = idx * pow;
return p;
},[0]);
return numList.reduce(function (p, v) {
p += v;
return p;
}, 0)-hz;
}
写完了感觉别人好, 一段代码就把所有的事情做完了. 后面还是想办法把BigInteger.js
弄过来, 然后好好把玩
2023-05-16 续.
https://github.com/peterolson/BigInteger.js这个地址是有效的. 另外,
base_symbols
的值也修正了.
原文: https://stackoverflow.com/questions/49541184/anyway-to-compress-a-string-to-something-smaller-in-javascript-and-make-it-reve
测试一下别人的代码:
var input = 'SigV1i8njyrAGrbAfHRNdM3fmEu3kd7keGsqTTDG3Wt3tXqT153eFya2JsEigrK7Pjmh6HhEQLp5bmNXyeHsKNELW7cD3';
var a = baseConvert(input, 62, 80);
var b = baseConvert(a, 80, 62);
console.log('%s\n%s\n%s\n', input, a, b);