Add or Subtract From 64bit Integer in Javascript

故事扮演 提交于 2020-01-04 02:53:28

问题


Is there a simple way (hoping for a small function, not a library) to add or subtract from a 64bit integer in JavaScript?

Example 64bit int: 291270990346989568

Background: I am working with the Twitter API which has 64bit tweet ID's. I'd like to add or subtract one from those IDs to manipulate what results I get back from Twitter.


回答1:


The following code does what you've described.

Splitting, adding or subtracting, then re-joining...

This code has both increment and decrement functions, and a test function with some edge cases. When splitting number strings and doing math on them, you need to consider what happens to "leading zeroes", so there's a padding function for that.

Thanks, Justin, for providing a JSFiddle with this solution.

/*
 * Prepend zeros to expand a given string to given length
 *
 * @var {String} numStr Number
 * @var {Number} len    Length to pad out to
 *
 * @returns {String}
 */
function pad0 (numStr,len) {
  while (numStr.length < len) {
    numStr = "0" + numStr;
  }
  return numStr
}

/*
 * Decrement the given (64 bit) integer.
 *
 * @var {String} int64  Postive non-zero integer, as a string
 *
 * @returns {String}
 */
function decrInt64 (int64) {
  var result = "";
  var midpt = Math.floor(int64.length/2);
  var upper = int64.substring(0,midpt);
  var lower = int64.substring(midpt);
  var upperVal = new Number(upper);
  var lowerVal = new Number(lower);

  if (lowerVal == 0) {
    if (upperVal == 0) {
      // We don't support negative numbers
      result = "*ERROR*"
    }
    else {
      // borrow 1
      result = pad0((--upperVal).toString(),upper.length) +
               (new Number("1"+lower) - 1).toString();
    }
  }
  else {
    var newLower = (lowerVal - 1).toString();
    result = upper + pad0(newLower,lower.length);
  }
  alert(result);
}

/*
 * Increment the given (64 bit) integer.
 *
 * @var {String} int64  Postive, as a string
 *
 * @returns {String}
 */
function incrInt64 (int64) {
  var result = "";
  var midpt = Math.floor(int64.length/2);
  var upper = int64.substring(0,midpt);
  var lower = int64.substring(midpt);
  var upperVal = new Number(upper);
  var lowerVal = new Number(lower);

  var newLower = (++lowerVal).toString();
  // Did we overflow?
  if (lower.length < newLower.length) {
    // Yes, carry the 1
    result = (++upperVal).toString() + newLower.substring(1);
  }
  else {
    result = upper + pad0(newLower,lower.length);
  }
  alert(result);
}

// Test function
window.displaymessage= function ()
{
  decrInt64("291270990046989568");
  incrInt64("291270990046989568");
  decrInt64("000000000000000000");
  incrInt64("000000000000000000");
  decrInt64("000000001000000000");
  incrInt64("000000001000000000");
  decrInt64("099999999999999999");
  incrInt64("099999999999999999");
  decrInt64("999999999999999999");
  incrInt64("999999999999999999");
}



回答2:


Addition of integer-formatted strings (base 10) of indefinite lengths can be done by splitting the string into segments of 9 characters, calculating + or - for that and then moving to the preceding 9 characters. This is because the largest 9 character number, 999999999 is 32-bit safe (as is 1999999999, which I used in subtraction).

The following code has 3 functions and the word integer is assumed to mean an integer-formatted string.

  • addAsString, takes two non-negative integers x and y, returns x + y
  • subtractAsString, takes two non-negative integers x and y, |x| >= |y|, returns x - y
  • addORsub, takes any two integers x and y, returning x + y

I've tried to explain what is happening via comments in the code

// Indefinate length addition
function addAsString(x, y) { // x, y strings
    var s = '';
    if (y.length > x.length) { // always have x longer
        s = x;
        x = y;
        y = s;
    }
    s = (parseInt(x.slice(-9),10) + parseInt(y.slice(-9),10)).toString(); // add last 9 digits
    x = x.slice(0,-9); // cut off last 9 digits
    y = y.slice(0,-9);
    if (s.length > 9) { // if >= 10, add in the 1
        if (x === '') return s; // special case (e.g. 9+9=18)
        x = addAsString(x, '1');
        s = s.slice(1);
    } else if (x.length) { // if more recursions to go
        while (s.length < 9) { // make sure to pad with 0s
            s = '0' + s;
        }
    }
    if (y === '') return x + s; // if no more chars then done, return
    return addAsString(x, y) + s; // else recurse, next digit
}

// Indefinate length subtraction (x - y, |x| >= |y|)
function subtractAsString(x, y) {
    var s;
    s = (parseInt('1'+x.slice(-9),10) - parseInt(y.slice(-9),10)).toString(); // subtract last 9 digits
    x = x.slice(0,-9); // cut off last 9 digits
    y = y.slice(0,-9);
    if (s.length === 10 || x === '') { // didn't need to go mod 1000000000
        s = s.slice(1);
    } else { // went mod 1000000000, inc y
        if (y.length) { // only add if makes sense
            y = addAsString(y, '1');
        } else { // else set
            y = '1';
        }
        if (x.length) {
            while (s.length < 9) { // pad s
                s = '0' + s;
            }
        }
    }
    if (y === '') { // finished
        s = (x + s).replace(/^0+/,''); // dont return all 0s
        return s;
    }
    return subtractAsString(x, y) + s;
}

// Indefinate length addition or subtraction (via above)
function addORsub(x, y) {
    var s = '';
    x = x.replace(/^(-)?0+/,'$1').replace(/^-?$/,'0'); // -000001 = -1
    y = y.replace(/^(-)?0+/,'$1').replace(/^-?$/,'0'); // -000000 =  0
    if (x[0] === '-') { // x negative
        if (y[0] === '-') { // if y negative too
            return '-' + addAsString(x.slice(1), y.slice(1)); // return -(|x|+|y|)
        }
        return addORsub(y, x); // else swap
    }
    if (y[0] === '-') { // x positive, y negative
        s = y.slice(1);
        if (s.length < x.length || (s.length === x.length && s < x)) return subtractAsString(x, s) || '0'; // if |x|>|y|, return x-y
        if (s === x) return '0'; // equal then 0
        s = subtractAsString(s, x); // else |x|<|y|
        s = (s && '-' + s) || '0';
        return s; // return -(|y|-x)
    }
    return addAsString(x, y); // x, y positive, return x+y
}

Example usage (fiddle)

var i = addORsub('291270990346989568', '1'); // add
i === '291270990346989569';

i = addORsub('291270990346989568', '-1'); // subtract
i === '291270990346989567';


来源:https://stackoverflow.com/questions/14347441/add-or-subtract-from-64bit-integer-in-javascript

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!