将大数字从二进制转换为十进制并返回JavaScript

时间:2016-09-05 16:23:51

标签: javascript

我在JavaScript中有一个非常大的数字表示为二进制文件:

 var largeNumber = '11010011010110100001010011111010010111011111000010010111000111110011111011111000001100000110000011000001100111010100111010101110100010001011010101110011110000011000001100000110000011001001100000110000011000001100000110000111000011100000110000011000001100000110000011000010101100011001110101101001100110100100000110000011000001100000110001001101011110110010001011010001101011010100011001001110001110010100111011011111010000110001110010101010001111010010000101100001000001100001011000011011111000011110001110111110011111111000100011110110101000101100000110000011000001100000110000011010011101010110101101001111101001010010111101011000011101100110010011001001111101'

当我使用parseInt(largeNumber, 10) l将其转换为十进制时,它会给我1.5798770299367407e+199但是当我尝试将其转换回二进制时:

parseInt(`1.5798770299367407e+199`, 2)

当我期望看到1的原始二进制表示时,它返回parseInt(我认为这与largeNumber如何通过舍入值有关)。你能解释一下这种行为吗?我如何在JavaScript中将其转换回原始状态?

编辑:这个问题是我的实验结果,我正在玩存储和传输大量布尔数据。 largeNumber表示集合[true,true,false,true ...]的布尔值,必须在客户端,客户端工作者和服务器之间共享。

4 个答案:

答案 0 :(得分:6)

正如Andrew L.'s answer和几位评论者所述,您的largeNumber超出了JavaScript可以表示为普通数字中的整数而不会丢失精度 - 9.007199254740991e+15

如果你想使用更大的整数,你需要一个BigInt库或其他专用代码。

下面是一些代码,演示了如何在不同的基本表示之间转换任意大的正整数,表明largeNumber的精确十进制表示是

  

15 798 770 299 367 407 029 725 345 423 297 491 683 306 908 462 684 165 669 735 033 278 996 876 231 474 309 788 453 071 122 111 686 268 816 862 247 538 905 966 252 886 886 438 931 450 432 740 640 141 331 094 589 505 960 171 298 398 097 197 475 262 433 234 991 526 525



function parseBigInt(bigint, base) {
  //convert bigint string to array of digit values
  for (var values = [], i = 0; i < bigint.length; i++) {
    values[i] = parseInt(bigint.charAt(i), base);
  }
  return values;
}

function formatBigInt(values, base) {
  //convert array of digit values to bigint string
  for (var bigint = '', i = 0; i < values.length; i++) {
    bigint += values[i].toString(base);
  }
  return bigint;
}

function convertBase(bigint, inputBase, outputBase) {
  //takes a bigint string and converts to different base
  var inputValues = parseBigInt(bigint, inputBase),
    outputValues = [], //output array, little-endian/lsd order
    remainder,
    len = inputValues.length,
    pos = 0,
    i;
  while (pos < len) { //while digits left in input array
    remainder = 0; //set remainder to 0
    for (i = pos; i < len; i++) {
      //long integer division of input values divided by output base
      //remainder is added to output array
      remainder = inputValues[i] + remainder * inputBase;
      inputValues[i] = Math.floor(remainder / outputBase);
      remainder -= inputValues[i] * outputBase;
      if (inputValues[i] == 0 && i == pos) {
        pos++;
      }
    }
    outputValues.push(remainder);
  }
  outputValues.reverse(); //transform to big-endian/msd order
  return formatBigInt(outputValues, outputBase);
}

var largeNumber =
  '1101001101011010000101001111101001011101' + 
  '1111000010010111000111110011111011111000' +
  '0011000001100000110000011001110101001110' +
  '1010111010001000101101010111001111000001' +
  '1000001100000110000011001001100000110000' +
  '0110000011000001100001110000111000001100' +
  '0001100000110000011000001100001010110001' +
  '1001110101101001100110100100000110000011' +
  '0000011000001100010011010111101100100010' +
  '1101000110101101010001100100111000111001' +
  '0100111011011111010000110001110010101010' +
  '0011110100100001011000010000011000010110' +
  '0001101111100001111000111011111001111111' +
  '1000100011110110101000101100000110000011' +
  '0000011000001100000110100111010101101011' +
  '0100111110100101001011110101100001110110' +
  '0110010011001001111101';

//convert largeNumber from base 2 to base 10
var largeIntDecimal = convertBase(largeNumber, 2, 10);


function groupDigits(bigint){//3-digit grouping
  return bigint.replace(/(\d)(?=(\d{3})+$)/g, "$1 ");
}

//show decimal result in console:
console.log(groupDigits(largeIntDecimal));

//converting back to base 2:
var restoredOriginal = convertBase(largeIntDecimal, 10, 2);

//check that it matches the original:
console.log(restoredOriginal === largeNumber);
&#13;
&#13;
&#13;

答案 1 :(得分:2)

当你将它转换回二进制时,你不会将它解析为基数2,这是错误的。您还试图将整数解析为浮点数,这可能导致不精确。有了这条线:

parseInt(`1.5798770299367407e+199`, 2)

你告诉JS将基数10解析为基数2!您需要做的是将其转换为二进制(请注意使用parseFloat):

var largeNumber = '11010011010110100001010011111010010111011111000010010111000111110011111011111000001100000110000011000001100111010100111010101110100010001011010101110011110000011000001100000110000011001001100000110000011000001100000110000111000011100000110000011000001100000110000011000010101100011001110101101001100110100100000110000011000001100000110001001101011110110010001011010001101011010100011001001110001110010100111011011111010000110001110010101010001111010010000101100001000001100001011000011011111000011110001110111110011111111000100011110110101000101100000110000011000001100000110000011010011101010110101101001111101001010010111101011000011101100110010011001001111101';

//intLN is integer of large number
var intLN = parseFloat(largeNumber, 2); //here, you used base 10 to parse as integer, Incorrect
console.log(intLN);

var largeNumberConvert = intLN.toString(2); //here, we convert back to binary with toString(radix).
console.log(largeNumberConvert);

之前,您将十进制转换为二进制。您需要做的是调用toString(radix)将其转换回二进制,所以:

var binaryRepresentation = integerFormOfLargeNumber.toString(2);

如果查看输出,您会看到:

Infinity
Infinity

由于您的二进制数非常大,因此会影响结果。因为JS最多支持64位,所以数字太大了。它导致Infinity并且不精确。如果您尝试将largeNumberConvert从二进制重新转换为十进制,如下所示:

parseInt(largeNumberConvert, 10);

您可以看到它输出Infinity

答案 2 :(得分:1)

如果要传输大量二进制数据,则应使用BigInt。 BigInt允许您表示任意数量的位。

// parse large number from string
let numString = '1101001101011010000101001111101001011101111100001001'

// as number
let num = BigInt('0b' + numString)

// now num holds large number equivalent to numString
console.log(num)  // 3718141639515913n

// print as base 2
console.log(num.toString(2))  // 1101001101011010000101001111101001011101111100001001

辅助功能

// some helper functions

// get kth bit from right
function getKthBit(x, k){
  return (x & (1n << k)) >> k;
}

// set kth bit from right to 1
function setKthBit(x, k){
  return (1n << k) | x;
}

// set kth bit from right to 0
function unsetKthBit(x, k){
  return (x & ~(1n << k));
}

getKthBit(num, 0n);  
// 1n

getKthBit(num, 5n);  
// 0n

setKthBit(num, 1n).toString(2); 
// 1101001101011010000101001111101001011101111100001011

setKthBit(num, 4n); 
// 1101001101011010000101001111101001011101111100011001

unsetKthBit(num, 0n).toString(2);
// 1101001101011010000101001111101001011101111100001000

unsetKthBit(num, 0n).toString(2);
// 1101001101011010000101001111101001011101111100000001

为方便起见,如果要序列化回客户端,则可能需要将其添加到BigInt。然后,您可以将其读回为字符串。否则,您将收到“ Uncaught TypeError:不知道如何序列化BigInt”,因为某种原因Javascript Object Notation不知道如何序列化Javascript中的一种类型。

    Object.defineProperty(BigInt.prototype, "toJSON", {
        get() {
            "use strict";
            return () => this.toString() + 'n';
        }
    });

答案 3 :(得分:0)

BigInt内置于js

function parseBigInt(str, base=10) {
  base = BigInt(base)
  var bigint = BigInt(0)
  for (var i = 0; i < str.length; i++) {
    var code = str[str.length-1-i].charCodeAt(0) - 48; if(code >= 10) code -= 39
    bigint += base**BigInt(i) * BigInt(code)
  }
  return bigint
}
parseBigInt('11010011010110100001010011111010010111011111000010010111000111110011111011111000001100000110000011000001100111010100111010101110100010001011010101110011110000011000001100000110000011001001100000110000011000001100000110000111000011100000110000011000001100000110000011000010101100011001110101101001100110100100000110000011000001100000110001001101011110110010001011010001101011010100011001001110001110010100111011011111010000110001110010101010001111010010000101100001000001100001011000011011111000011110001110111110011111111000100011110110101000101100000110000011000001100000110000011010011101010110101101001111101001010010111101011000011101100110010011001001111101', 2)
// 15798770299367407029725345423297491683306908462684165669735033278996876231474309788453071122111686268816862247538905966252886886438931450432740640141331094589505960171298398097197475262433234991526525n