Javascript - parse string to long

前端 未结 3 354
南方客
南方客 2021-01-02 02:11

I have a working script in python doing string to integer conversion based on specified radix using long(16):

modulus=public_key[\"n\"]    
modu         


        
相关标签:
3条回答
  • 2021-01-02 02:46

    As described in this answer, JavaScript numbers cannot represent integers larger than 9.007199254740991e+15 without loss of precision.

    Working with larger integers in JavaScript requires a BigInt library or other special-purpose code, and large integers will then usually be represented as strings or arrays.

    Re-using code from this answer helps to convert the hexadecimal number representation

    8079d7ae567dd2c02dadd1068843136314fa3893fa1fb1ab331682c6a85cad62b208d66c9974bbbb15d52676fd9907efb158c284e96f5c7a4914fd927b7326c40efa14922c68402d05ff53b0e4ccda90bbee5e6c473613e836e2c79da1072e366d0d50933327e77651b6984ddbac1fdecf1fd8fa17e0f0646af662a8065bd873

    to its decimal representation

    90218878289834622370514047239437874345637539049004160177768047103383444023879266805615186962965710608753937825108429415800005684101842952518531920633990402573136677611127418094912644368840442620417414685225340199872975797295511475162170060618806831021437109054760851445152320452665575790602072479287289305203

    as demonstrated in the following snippet:

    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 =
    '8079d7ae567dd2c02dadd1068843136314fa389'+
    '3fa1fb1ab331682c6a85cad62b208d66c9974bb'+
    'bb15d52676fd9907efb158c284e96f5c7a4914f'+
    'd927b7326c40efa14922c68402d05ff53b0e4cc'+
    'da90bbee5e6c473613e836e2c79da1072e366d0'+
    'd50933327e77651b6984ddbac1fdecf1fd8fa17'+
    'e0f0646af662a8065bd873';
    
    //convert largeNumber from base 16 to base 10
    var largeIntDecimal = convertBase(largeNumber, 16, 10);
    
    //show decimal result in console:
    console.log(largeIntDecimal);
    
    //check that it matches the expected output:
    console.log('Matches expected:',
      largeIntDecimal === '90218878289834622370514047239437874345637539049'+
        '0041601777680471033834440238792668056151869629657106087539378251084294158000056'+
        '8410184295251853192063399040257313667761112741809491264436884044262041741468522'+
        '5340199872975797295511475162170060618806831021437109054760851445152320452665575'+
        '790602072479287289305203'
    );
    
    //check that conversion and back-conversion results in the original number
    console.log('Converts back:',
      convertBase(convertBase(largeNumber, 16, 10), 10, 16) === largeNumber
    );

    0 讨论(0)
  • 2021-01-02 02:51

    Using the built in api parseInt, you can get upto 100 digts of accuracy on Firefox and 20 digits of accuracy on Chrome.

    a = parseInt('8079d7ae567dd2c02dadd1068843136314fa3893fa1fb1ab331682c6a85cad62b208d66c9974bbbb15d52676fd9907efb158c284e96f5c7a4914fd927b7326c40efa14922c68402d05ff53b0e4ccda90bbee5e6c473613e836e2c79da1072e366d0d50933327e77651b6984ddbac1fdecf1fd8fa17e0f0646af662a8065bd873', 16)
    
    a.toPrecision(110)
    > Uncaught RangeError: toPrecision() argument must be between 1 and 21
    
    # Chrome
    a.toPrecision(20)
    "9.0218878289834615508e+307"  
    
    # Firefox
    a.toPrecision(100)
    "9.021887828983461550807409292694387726882781812072572899692574101215517323445643340153182035092932819e+307"
    

    From the ECMAScript Spec,

    1. Let p be ? ToInteger(precision).
      ...
    2. If p < 1 or p > 100, throw a RangeError exception.
    0 讨论(0)
  • 2021-01-02 03:00

    Numbers in JavaScript are floating point so they always lose precision after a certain digit. To have unlimited numbers one could rather use an array of numbers from 0 to 9, which has an unlimited range. To do so based on the hex string input, i do a hex to int array conversion, then I use the double dabble algorithm to convert the array to BCD. That can be printed easily:

    const hexToArray = arr => arr.split("").map(n => parseInt(n,16));
    
    
    const doubleDabble = arr => {
      var l = arr.length;
      for( var b = l * 4; b--;){
    
        //add && leftshift
        const overflow = arr.reduceRight((carry,n,i) => {
    
          //apply the >4 +3, then leftshift
          var shifted = ((i < (arr.length - l ) && n>4)?n+3:n ) << 1;
    
          //just take the right four bits and add the eventual carry value
          arr[i] = (shifted & 0b1111) | carry;
    
          //carry on
          return shifted > 0b1111;
        }, 0);
        // we've exceeded the current array, lets extend it:
        if(overflow) arr.unshift(overflow);
      }
      return arr.slice(0,-l);
    };
    
    const arr = hexToArray("8079d7");
    const result = doubleDabble(arr);      
    console.log(result.join(""));
    

    Try it

    0 讨论(0)
提交回复
热议问题