在 JavaScript 中将数字转换为基数 64 的最快方法?

新手上路,请多包涵

在 JavaScript 中,您可以将数字转换为具有特定 基数 的字符串表示形式,如下所示:

 (12345).toString(36) // "9ix"

…您可以像这样将其转换回常规数字:

 parseInt("9ix", 36) // 12345

36 是您可以指定的最高基数。它显然使用字符 0-9a-z 作为数字(总共 36 个)。

我的问题:将数字转换为 base 64 表示的最快方法是什么(例如,使用 A-Z-_ digit )?


更新:有四个人发布了回复,说这个问题重复了,或者我正在寻找 Base64。我不是。

Base64 ”是一种用简单的 ASCII 字符集对二进制数据进行编码的方法,以使其在网络传输等方面是安全的(这样纯文本系统就不会混淆二进制文件)。

那不是我要问的。我问的是将 数字 转换为基数 64 字符串表示形式。 (JavaScript 的 toString(radix) 自动为任何不超过 36 的基数执行此操作;我需要一个自定义函数来获取基数 64。)


更新 2 :这里有一些输入和输出示例……

 0   → "0"
1   → "1"
9   → "9"
10  → "a"
35  → "z"
61  → "Z"
62  → "-"
63  → "_"
64  → "10"
65  → "11"
128 → "20"
etc.

原文由 callum 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 329
2 个回答

这是数字解决方案的草图(不是字节数组:)

仅适用于正数,忽略小数部分,并且没有真正测试——只是一个草图!

 Base64 = {

    _Rixits :
//   0       8       16      24      32      40      48      56     63
//   v       v       v       v       v       v       v       v      v
    "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/",
    // You have the freedom, here, to choose the glyphs you want for
    // representing your base-64 numbers. The ASCII encoding guys usually
    // choose a set of glyphs beginning with ABCD..., but, looking at
    // your update #2, I deduce that you want glyphs beginning with
    // 0123..., which is a fine choice and aligns the first ten numbers
    // in base 64 with the first ten numbers in decimal.

    // This cannot handle negative numbers and only works on the
    //     integer part, discarding the fractional part.
    // Doing better means deciding on whether you're just representing
    // the subset of javascript numbers of twos-complement 32-bit integers
    // or going with base-64 representations for the bit pattern of the
    // underlying IEEE floating-point number, or representing the mantissae
    // and exponents separately, or some other possibility. For now, bail
    fromNumber : function(number) {
        if (isNaN(Number(number)) || number === null ||
            number === Number.POSITIVE_INFINITY)
            throw "The input is not valid";
        if (number < 0)
            throw "Can't represent negative numbers now";

        var rixit; // like 'digit', only in some non-decimal radix
        var residual = Math.floor(number);
        var result = '';
        while (true) {
            rixit = residual % 64
            // console.log("rixit : " + rixit);
            // console.log("result before : " + result);
            result = this._Rixits.charAt(rixit) + result;
            // console.log("result after : " + result);
            // console.log("residual before : " + residual);
            residual = Math.floor(residual / 64);
            // console.log("residual after : " + residual);

            if (residual == 0)
                break;
            }
        return result;
    },

    toNumber : function(rixits) {
        var result = 0;
        // console.log("rixits : " + rixits);
        // console.log("rixits.split('') : " + rixits.split(''));
        rixits = rixits.split('');
        for (var e = 0; e < rixits.length; e++) {
            // console.log("_Rixits.indexOf(" + rixits[e] + ") : " +
                // this._Rixits.indexOf(rixits[e]));
            // console.log("result before : " + result);
            result = (result * 64) + this._Rixits.indexOf(rixits[e]);
            // console.log("result after : " + result);
        }
        return result;
    }
}

更新:这是对上面的一些(非常轻量级的)测试,用于在具有 console.log 的 NodeJs 中运行。

 function testBase64(x) {
    console.log("My number is " + x);
    var g = Base64.fromNumber(x);
    console.log("My base-64 representation is " + g);
    var h = Base64.toNumber(g);
    console.log("Returning from base-64, I get " + h);
    if (h !== Math.floor(x))
        throw "TEST FAILED";
}

testBase64(0);
try {
    testBase64(-1);
    }
catch (err) {
    console.log("caught >>>>>>  " + err);
    }
try {
    testBase64(undefined);
    }
catch (err) {
    console.log("caught >>>>>>  " + err);
    }
try {
    testBase64(null);
    }
catch (err) {
    console.log("caught >>>>>>  " + err);
    }
try {
    testBase64(Number.NaN);
    }
catch (err) {
    console.log("caught >>>>>>  " + err);
    }
try {
    testBase64(Number.POSITIVE_INFINITY);
    }
catch (err) {
    console.log("caught >>>>>>  " + err);
    }
try {
    testBase64(Number.NEGATIVE_INFINITY);
    }
catch (err) {
    console.log("caught >>>>>>  " + err);
    }

for(i=0; i<100; i++)
    testBase64(Math.random()*1e14);

原文由 Reb.Cabin 发布,翻译遵循 CC BY-SA 3.0 许可协议

这是一个仅适用于 32 位整数的版本,即 -2147483648 和 2147483647(含)之间的任何数字。

我修改了 Reb Cabin 的最佳答案中的版本。这应该快一点,因为它使用位操作和查找表。

 Base64 = (function () {
    var digitsStr =
    //   0       8       16      24      32      40      48      56     63
    //   v       v       v       v       v       v       v       v      v
        "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+-";
    var digits = digitsStr.split('');
    var digitsMap = {};
    for (var i = 0; i < digits.length; i++) {
        digitsMap[digits[i]] = i;
    }
    return {
        fromInt: function(int32) {
            var result = '';
            while (true) {
                result = digits[int32 & 0x3f] + result;
                int32 >>>= 6;
                if (int32 === 0)
                    break;
            }
            return result;
        },
        toInt: function(digitsStr) {
            var result = 0;
            var digits = digitsStr.split('');
            for (var i = 0; i < digits.length; i++) {
                result = (result << 6) + digitsMap[digits[i]];
            }
            return result;
        }
    };
})();

例如,

 Base64.fromInt(-2147483648); // gives "200000"
Base64.toInt("200000"); // gives -2147483648

原文由 jahooma 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题