Java中的Karatsuba乘法,无限递归

时间:2014-02-12 21:13:46

标签: java recursion multiplication infinite

我正在尽我所能用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或类似的东西,然后它在此时无限循环。

3 个答案:

答案 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”:|。

可悲的是,没有人再看这个问题了。