我正在尽我所能用Java做Karatsuba实现,而且我失败了。可以请一些人看看我的代码并告诉我,我到底做错了什么?我一直在反对这一点,谷歌就像疯了一样,没有发现让我失望。我只是没有看到friggin的问题是什么!
这里你去:
Random rand = new Random();
int lenght = 200000;
int lenght1 = 200000;
BigInteger value = new BigInteger(lenght, rand);
BigInteger value1 = new BigInteger(lenght1, rand);
doTheMath(lenght, lenght1, value, value1);
private BigInteger doTheMath(int len, int len1, BigInteger var, BigInteger var1)
{
// A = A1*alpha + A0; where alpha is a suitable power of the radix
int alpha = 0;
BigInteger Z0 = null, Z1 = null, Z2 = null, result = null, A1 = null, A0 = null, B1 = null, B0 = null;
int nTemp = 0, nTemp1 = 0, nLenght = 0, nLenght1 = 0;
// we chose base 10 as our base
if(len > len1)
{alpha = (int) Math.pow(10, len1/2);}
else if(len <= len)
{alpha = (int) Math.pow(10, len/2);}
String converter = "" + alpha;
// we calculate A1 and B1 respectively
A1 = var.divide(new BigInteger(converter));
B1 = var1.divide(new BigInteger(converter));
// we calculate A0 and B0 respectively
// the formula used: A0 = A - (A1 * alpha)
A0 = var.subtract(A1.multiply(new BigInteger(converter)));
// the formula used: B0 = B - (B1 * alpha)
B0 = var1.subtract(B1.multiply(new BigInteger(converter)));
// Formulas:
// A*B = (A1*alpha+A0)*(B1*alpha+B0) = Z2*alpha^2+Z1*alpha+Z0
// Z2 = A1*B1
// Z1 = (A1+A0)*(B1+B0)-Z2-Z0
// Z0 = A0*B0
// recursively calculate the values of Z2, Z1 and Z0
if((A1.bitLength() >= 70000) || (A0.bitLength() >= 70000) || (B1.bitLength() >= 70000) || (B0.bitLength() >= 70000))
{
Z2 = doTheMath(A1.bitLength(), B1.bitLength(), A1, B1);
Z0 = doTheMath(A0.bitLength(), B0.bitLength(), A0, B0);
Z1 = doTheMath(A1.bitLength(), B1.bitLength(), A1.add(A0), B1.add(B0)).subtract(Z2).subtract(Z0);
}
else // if the length of the recursive operands that need multiplying is smaller than 100000 then do it normally, not recursively
{
Z2 = A1.multiply(B1);
Z0 = A0.multiply(B0);
Z1 = A1.add(A0).multiply(B1.add(B0)).subtract(Z2).subtract(Z0);
}
//result = Z2 * Math.pow(alpha, 2)+ Z1 * alpha + Z0;
result = Z2.multiply(new BigInteger(""+(int) Math.pow(alpha, 2))).add(Z1.multiply(new BigInteger(converter))).add(Z0);
return result;
}
我知道有些实现可以用来激励我,我可以从头开始;但我真的想知道我哪里出错了。在此先感谢大家,对不起烦恼:|。
编辑:我使用调试器运行它(虽然我现在正在工作但不能发布它)。它递归地向下,直到长度为70008 70009或类似的东西,然后它在此时无限循环。答案 0 :(得分:2)
使用此语句和您的初始条件看起来会出现问题,除非您打算截断它:
alpha = (int) Math.pow(10, len1/2);}
您试图将10 ^ 100000的结果转换为(int)
,其最大值只能为2,147,483,647,介于10 ^ 9和10 ^ 10之间。
我认为使用传递两个Math.Pow
值的double
函数并返回double
的任何方式都不能用于计算正确的alpha
组件一个int
,即使数字比10 ^ 100000更合理。
例如,Math.Pow(10,10)
返回double
10,000,000,000
的值。
将其投放到(int)
时会发生什么?
在C#中,您获得了(int)(Math.Pow(10,10))
1410065408
的值
答案 1 :(得分:1)
如果你总是得到无限递归,那就意味着这个条件
if((A1.bitLength() >= 70000) || (A0.bitLength() >= 70000) || (B1.bitLength() >= 70000) || (B0.bitLength() >= 70000))
总是让人满意。在if语句中,您有多次调用contains函数,这会导致无限递归。
答案 2 :(得分:0)
实际发现了问题。似乎就是这段代码:
if(len > len1)
{alpha = alpha.pow(len1/2);}
else if(len <= len1)
{alpha = alpha.pow(len/2);}
我将“alpha”更改为BigInteger并尝试使用上述代码。没有明显的原因,代码不起作用。例: 如果alpha = alpha.pow(len / 2);和alpha的初始值为“10”,len / 2的值为“100000”,表达式的计算结果为“332193”:|。
可悲的是,没有人再看这个问题了。