【问题标题】:karatsuba algorithm, Maximum call stack size exceededkaratsuba 算法,超出最大调用堆栈大小
【发布时间】:2016-11-22 07:09:44
【问题描述】:

我正在编写自己的 karatsuba algh 变体,但无法使其适用于非常大的整数

'use strict';

const karatsuba = function (x, y) {
  if (x < 10 || y < 10) return x * y;

  const strX = String(x);
  const strY = String(y);

  const n = Math.min(strX.length, strY.length);
  const m = Math.ceil(n / 2);

  const leftX = strX.slice(0, strX.length - m),
        rightX = strX.slice(strX.length - m, strX.length),

        leftY = strY.slice(0, strY.length - m),
        rightY = strY.slice(strY.length - m, strY.length);

  const prod1 = karatsuba(leftX, leftY),
        prod2 = karatsuba(rightX, rightY),
        prod3 = karatsuba(addAny(leftX, rightX), addAny(leftY, rightY));

  const a = prod1 + String(Math.pow(10, 2 * m)).slice(1),
        b = (prod3 - prod1 - prod2) + String(Math.pow(10, m)).slice(1),
        ab = addAny(a, b);

  return addAny(ab, prod2);
};

function addAny(a, b) {
  const MAX_INT = 9007199254740992,
      intA = parseInt(a),
      intB = parseInt(b);

  if ((intA + intB) < MAX_INT) return intA + intB;

  return sumStrings(a + '', b + '');
}



function sumStrings(a, b) {
  let res = '', c = 0;

  a = a.split('');
  b = b.split('');

  while (a.length || b.length || c) {
    c += ~~a.pop() + ~~b.pop();
    res = c % 10 + res;
    c = c > 9;
  }

  return res.replace(/^0+/, '');
}

它适用于像 3957322621233333 和 5548313756335578 这样的整数 但是当我尝试将它与 76715432964249374812219365555 和 32141964835273822784327848699719 之类的大整数一起使用时,代码崩溃了

RangeError: Maximum call stack size exceeded

【问题讨论】:

  • 我无法在 Node.js 中重现该错误。但是计算结果是错误的:karatsuba('76715432964249374812219365555','32141964835273822784327848699719') == '1045731853714033916818600413783559075'
  • 这是我的测试用例:a = 3957322621234423; b = 7748313756335578;资源= 30662577304368647842211393201494; console.log(karatsuba(a, b) == res); ----工作正常,并且数字最低---- a = 34215432964249374812219364786397; b = 94541964835273822784327848699719; res = 3234794260129733170788831535430575611379062580407060392628922443;范围错误:(
  • 为什么你认为(prod3 - prod1 - prod2) 会在你需要调用特殊函数来添加字符串时才起作用?减法也使用相同的方法。
  • 是的,你说得对,我也想过,谢谢!

标签: javascript algorithm recursion


【解决方案1】:

您在通话中省略了引号,不是吗?

> katsuba(76715432964249374812219365555,32141964835273822784327848699719)
RangeError: Maximum call stack size exceeded
    at karatsuba (repl:2:5)
    at karatsuba (repl:16:15)
    at karatsuba (repl:17:9)
    at karatsuba (repl:17:9)
    at karatsuba (repl:17:9)
    at karatsuba (repl:17:9)
    at karatsuba (repl:17:9)
    at karatsuba (repl:17:9)
    at karatsuba (repl:17:9)
    at karatsuba (repl:17:9)

76715432964249374812219365555 大于 5**53,代码中的 MAX_INT。数字文字被隐式转换为浮点数7.671543296424938e+28,您的算法在数字格式上卡住了。

尽管如此,您的实现还是有一些错误,因为即使您使用字符串文字,计算结果也是错误的:

> karatsuba('76715432964249374812219365555', '32141964835273822784327848699719')
'1045731853714033916818600413783559075'

而不是

'2465784748659709650840276767201870909665028593909797886779045'

【讨论】:

  • 是的,你的权利 - 即使使用字符串参数,得到错误的数字......可能我需要使用另一个函数来处理字符串来减去数字,认为问题就在这里......也许我必须在这里只使用字符串参数。谢谢!
  • @vanless,Bergi 已经提到您不能使用内置的减号运算符。我看到的另一个错误是String(Math.pow(10, m)).slice(1)。试试m=200 会发生什么。您可以改用Array(m+1).join('0')。
  • 哦,天哪,谢谢!它的工作!)伙计们,我爱你,堆栈溢出太多了)))
猜你喜欢
  • 1970-01-01
  • 2015-10-24
  • 2015-12-29
  • 2017-12-27
  • 2020-12-06
  • 2018-02-06
  • 2020-06-28
  • 2016-02-28
  • 2019-05-21
相关资源
最近更新 更多