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

在JavaScript中,您可以使用特定的基数将数字转换为string表示forms,如下所示:

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

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

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

36是您可以指定的最高基数。 它显然使用字符0-9az的数字(总计36)。

我的问题:将数字转换为基本64位表示的最快方法是什么(例如,使用AZ ,而-_是多余的28位数)?


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

“ Base64 ”是一种在简单的ASCII字符集中编码二进制数据的方式,以便通过networking传输等方式保证安全(使纯文本系统不会让二进制文件出现乱码)。

这不是我所问的。 我在询问如何将数字转换为基数为64的string表示forms。 (JavaScript的toString(radix)自动为任何基数达到36;我需要一个自定义函数来获得基数64)。


更新2 :这里有一些input和输出的例子…

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

这里是一个NUMBERS解决scheme的草图(不是字节数组:)

只有正数,忽略小数部分,而不是真正的testing – 只是一个素描!

 Base64 = { _Rixits : // 0 8 16 24 32 40 48 56 63 // vvvvvvvvv "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; } } 

更新:这里有一些(非常轻量级)的testing,在NodeJs中运行console.log。

 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); 

这是32位整数的一个版本,也就是-2147483648和2147483647(含)之间的任何数字。

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

 Base64 = (function () { var digitsStr = // 0 8 16 24 32 40 48 56 63 // vvvvvvvvv "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 

我正在寻找解决同样问题的解决方法,但是对于ActionScript(AS3) ,很明显许多人将Base64编码“base 64中的数字”(基数为64)混淆。

绝大多数网站提供“计算密码学”解决scheme,而不是math 。 作为解决scheme,这对于我们所需的转换没有用处。

在这个咨询之前,知道方法toString(radix)和parseInt(radix),我用hex数字(基数16)在两种颜色,和其他function。

然而,在AS3JS中都不存在用于从基数64转换的数值方法。

在来到这个网站之前,我发现:

  1. 在各种在线计算器中, 基数64不是从头开始的,而是A。
    例如: convertix.com & alfredo4570.net
  2. 基数64由以下几组有序字符组成:AZ,az,0-9,+和/(这些我定义了一个常量:STR64)

为了避免与encryption方法混淆,要使用的方法基于众所周知的名称:

  • toString / to64String
  • parseInt / to64Parse

代码被写在AS3中 ,但非常清楚(与JS共同)。

注意:推荐使用的数量在1 * 10以下

最后,包括一个操作的例子和结果。

 const STR64:Array = ('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/').split( '' ); // TRANSFORM NUMBERS BETWEEN radix 10 AND radix 64 /** Methods based on answers shared in: * @url http://stackoverflow.com/questions/6213227/fastest-way-to-convert-a-number-to-radix-64-in-javascript */ // METHODS /** to64String: Method to transform a radix 10 number to radix 64 number (as string) * @param input Number for transform to radix 64 (as String) * @param current String data (don't needed in request) * @return String Number in radix 64 as String; * * @based http://stackoverflow.com/users/383780/monocle * @based base64( Method for number to string - NOT string part ) */ function to64String( input:Number, current:String = '' ):String { if ( input < 0 && current.length == 0 ){ input = input * - 1; } var modify:Number = input % 64; var remain:Number = Math.floor( input / 64 ); var result:String = STR64[ modify ] + current; return ( remain <= 0 ) ? result : to64String( remain, result ); } /** to64Parse: Method for transform a number in radix 64 (as string) in radix 10 number * @param input Number in radix 64 (as String) to transform in radix 10 * @return Number in radix 10 * * @based http://stackoverflow.com/users/520997/reb-cabin * @based Base64.toNumber( Method for string to number ) */ function to64Parse ( input:String ):Number { var result:Number = 0; var toProc:Array = input.split( '' ); var e:String; for ( e in toProc ){ result = ( result * 64 ) + STR64.indexOf( toProc[ e ] ); } return result; } // TEST var i:int = 0; var max:Number = 1000000000000; var min:Number = 0; for ( i == 0; i < 20; i++ ){ var num:Number = ( Math.ceil( Math.random() * ( max - min + 1 ) ) + min ); var s64:String = to64String( num ); var ret:Number = to64Parse ( s64 ); trace( i + '\t# ' + num + '\t' + s64 + '\t' + ret + '\t' + ( ret == num ) ) } // TEST RESULT /* 0 # 808936734685 LxYYv/d 808936734685 true 1 # 931332556532 NjXvwb0 931332556532 true 2 # 336368837395 E5RJSMT 336368837395 true 3 # 862123347820 Mi6jk9s 862123347820 true 4 # 174279278611 CiT2sAT 174279278611 true 5 # 279361353722 EELO/f6 279361353722 true 6 # 435602995568 GVr9jlw 435602995568 true 7 # 547163526063 H9lfNOv 547163526063 true 8 # 188017380425 CvGtYxJ 188017380425 true 9 # 720098771622 KepO0Km 720098771622 true 10 # 408089106903 F8EAZnX 408089106903 true 11 # 293941423763 ERwRi6T 293941423763 true 12 # 383302396164 Fk+mmkE 383302396164 true 13 # 695998940618 KIMxQXK 695998940618 true 14 # 584515331314 IgX1CTy 584515331314 true 15 # 528965753970 Hso0Nxy 528965753970 true 16 # 5324317143 E9WqHX 5324317143 true 17 # 772389841267 LPWBalz 772389841267 true 18 # 954212692102 N4rgjCG 954212692102 true 19 # 867031893694 MnfIMa+ 867031893694 true */ 

我为这种types的操作( power-radix)编写了一个npm模块,它可以帮助你。 您可以将任何数字从任何基数转换为用户定义的字符编码中的任何基数。

例如:

 var base = ['Q', 'W', 'E', 'R', 'T', 'Y', 'I', 'O', 'U']; new PowerRadix([1, 0], 10).toArray(base); // ['W', 'Q'] new PowerRadix('10', 10).toArray(base); // ['W', 'Q'] new PowerRadix(10, 10).toArray(base); // ['W', 'Q'] new PowerRadix([1, 0], 10).toString(base); // "WQ" new PowerRadix('10', 10).toString(base); // "WQ" new PowerRadix(10, 10).toString(base); // "WQ" 

该模块还支持自定义源基数编码。

 new PowerRadix('ba', ['a', 'b']); // base 2 source radix, uses 'a' = 0 & 'b' = 1 character set. new PowerRadix('ba', ['a', 'b']).toString(10); // returns "2" 

如果您正在使用NodeJS,则可以使用以下代码:

 var base64 = Buffer.from([i>>24,i>>16,i>>8,i]).toString('base64').substr(0,6); 

这是一个不同的看法

 function base64(value) { if (typeof(value) === 'number') { return base64.getChars(value, ''); } if (typeof(value) === 'string') { if (value === '') { return NaN; } return value.split('').reverse().reduce(function(prev, cur, i) { return prev + base64.chars.indexOf(cur) * Math.pow(64, i); }, 0); } } base64.chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-_"; base64.getChars = function(num, res) { var mod = num % 64, remaining = Math.floor(num / 64), chars = base64.chars.charAt(mod) + res; if (remaining <= 0) { return chars; } return base64.getChars(remaining, chars); }; 

我知道的问题是Java脚本,但这里是一个在Java解决scheme,你可能很容易地将其转换。

 private String toShortString(BigInteger value, String language) { StringBuilder stringBuilder = new StringBuilder(); BigInteger length = BigInteger.valueOf(language.length()); while (value.compareTo(BigInteger.ZERO) > 0){ int index = value.mod(length).intValue(); stringBuilder.append(language.charAt(index)); value = value.divide(length); } return stringBuilder.reverse().toString(); } 

用法

  BigInteger value = BigInteger.valueOf(2).pow(128); System.out.println(value); System.out.println(value.toString(16)); System.out.println(toShortString(value, "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()-=_+")); 

产量

340282366920938463463374607431768211456
100000000000000000000000000000000
8HS#phQaCO3849pE + ^ EL4

如果您将其转换为Java Script,请编辑此问题并在下面添加它。

以下实现将正数,负数和非整数转换为任意的基数。 转换回十进制很容易以类似的方式实现:

 function toAnyBase(num, base) { if (!Number.isInteger(base) || base < 2) throw new RangeError("toAnyBase() base argument must be an integer >= 2"); if (!Number.isFinite(num)) return num.toString(); if (num < 0) return "-" + toAnyBase(-num, base); const digits = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ#_", inv_base = 1 / base; var result = "", residual; // Integer part: residual = Math.trunc(num); do { result = digits.charAt(residual % base) + result; residual = Math.trunc(residual * inv_base); } while (residual != 0); // Fractional part: residual = num % 1; if (residual != 0) { result += "."; var max = 1000; do { residual *= base; result += digits.charAt(Math.trunc(residual)); residual %= 1; } while (residual != 0 && --max != 0); } return result; } console.log(toAnyBase( 64, 64)); // "10" console.log(toAnyBase(-1.5, 64)); // "-1.w" 

那么,你可以使用任何Javascript Base64库:也许这个问题的答案呢?

编辑:二进制数据本质上只是一个字节序列。 如果你假设字节代表一个单一的数字,你可以将字节序列表示为一个64位的string。 解码他们,并做一些微不足道的字节数来得到一个数字。 将数字转换为一个字节序列并进行编码以获得一个string。 似乎很合理,除非你是以某种方式投入在string中使用的特定字符。

在mozilla或webkit浏览器中,您可以使用btoa()和atob()对base64进行编码和解码。