3

有没有一种简单的方法(希望是一个小函数,而不是一个库)在 JavaScript 中从 64 位整数中加减?

示例 64 位整数:291270990346989568

背景:我正在使用具有 64 位推文 ID 的 Twitter API。我想从这些 ID 中添加或减去一个,以操纵我从 Twitter 返回的结果。

4

2 回答 2

2

以下代码执行您所描述的操作。

拆分,加减,然后重新加入......

此代码具有递增和递减函数,以及带有一些边缘情况的测试函数。在拆分数字字符串并对它们进行数学运算时,您需要考虑“前导零”会发生什么,因此有一个填充函数。

感谢 Justin 提供了带有此解决方案的 JSFiddle

/*
 * 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");
}
于 2013-01-15T23:41:48.767 回答
1

添加不定长度的整数格式字符串(以 10 为底)可以通过将字符串拆分为 9 个字符的段来完成,计算或然后移动到前面的 9 个字符。这是因为最大的 9 个字符数是 32 位安全的(就像我在减法中使用的那样)。+-9999999991999999999

以下代码有 3 个函数,并且假定整数一词表示整数格式的字符串

  • addAsString, 接受两个非负整数xy, 返回x + y
  • subtractAsString, 接受两个非负整数x并且y, |x| >= |y|, 返回x - y
  • addORsub, 接受任意两个整数xy, 返回x + y

我试图通过代码中的注释来解释发生了什么

// 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
}

示例用法(小提琴

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

i = addORsub('291270990346989568', '-1'); // subtract
i === '291270990346989567';
于 2013-01-15T22:10:00.103 回答