【发布时间】: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