java - 使用 BigInteger 的 Karatsuba 乘法

标签 java algorithm biginteger

我首先使用 long 编写了 Karatsuba 算法的代码。我认为它完美无缺。使用相同的逻辑,我将代码转换为 BigInteger,但由于某些原因,它给出了 StackOverflowError。

我想不通为什么。请帮忙。


EDIT1: long 的代码也有一个逻辑缺陷。我不确定是什么。

EDIT2: long 的代码现在可以工作了。我错误地将“%”运算符换成了“/”。

EDIT3:现在一切都很好。我将 .xor 更改为 .pow 并将 == 更改为 .equals 并修复了返回语句中的一些括号问题。谢谢大家的帮助!


正确代码如下:

public static BigInteger karatsuba3(BigInteger i, BigInteger j){
    if (i.compareTo(Ten) == -1 || j.compareTo(Ten) == -1)
        return i.multiply(j);
    String length = getLength(i.max(j));
    BigInteger n = new BigInteger(length);
    if (n.mod(Two).equals(One))
        n = n.add(One);

    BigInteger a = i.divide(Ten.pow(n.divide(Two).intValue()));
    BigInteger b = i.mod(Ten.pow(n.divide(Two).intValue()));
    BigInteger c = j.divide(Ten.pow(n.divide(Two).intValue()));
    BigInteger d = j.mod(Ten.pow(n.divide(Two).intValue()));

    BigInteger first = karatsuba3(a,c);
    BigInteger second = karatsuba3(b,d);
    BigInteger third = karatsuba3(a.add(b),c.add(d));

    return ((first.multiply(Ten.pow(n.intValue()))).add ((((third.subtract(first)).subtract( second))).multiply(Ten.pow(n.divide((new BigInteger("2"))).intValue()))).add(second));
}

Karatsuba 长代码:

public static long karatsuba1(long i, long j){
    if (i < 10 || j < 10) 
        return i*j;
    double n = getLength(Math.max(i,j));
    if (n%2 == 1)
        n++;
    long a = (long) (i/Math.pow(10,(n/2)));
    long b = (long) (i%Math.pow(10,(n/2)));
    long c = (long) (j/Math.pow(10,(n/2)));
    long d = (long) (j%Math.pow(10,(n/2)));

    long first = karatsuba1(a, c);
    long second = karatsuba1(b, d);
    long third = karatsuba1(a + b, c + d);

    return ((long) ((first * Math.pow(10, n)) + ((third - first - second) * Math.pow(10, (n/2))) + second));
}

public static int getLength( long a){
    String b = Long.toString(a);
    return b.length();
}

带有 BigInteger 代码的 Karatsuba:

public static BigInteger karatsuba3(BigInteger i, BigInteger j){
    BigInteger Ten = new BigInteger("10");
    if (i.compareTo(Ten) == -1 || j.compareTo(Ten) == -1)
        return i.multiply(j);
    String length = getLength(i.max(j));
    BigInteger n = new BigInteger(length);
    if (n.mod(new BigInteger("2")) == new BigInteger("1"))
        n.add(new BigInteger ("1"));

    BigInteger a = i.divide(Ten.xor(n.divide((new BigInteger("2")))));
    BigInteger b = i.mod(Ten.xor(n.divide((new BigInteger("2")))));
    BigInteger c = j.divide(Ten.xor(n.divide((new BigInteger("2")))));
    BigInteger d = j.mod(Ten.xor(n.divide((new BigInteger("2")))));

    BigInteger first = karatsuba3(a,c);
    BigInteger second = karatsuba3(b,d);
    BigInteger third = karatsuba3(a.add(b),c.add(d));

    return ((first.multiply(Ten.xor(n))).add (((third.subtract(first).subtract( second)))).multiply(Ten.xor(n.divide((new BigInteger("2"))))).add(second));
}

public static String getLength( BigInteger a){
    String b = a.toString();
    return Integer.toString(b.length());
}

最佳答案

在第一个片段中,这一行在我看来是错误的:

long d = (long) (j/Math.pow(10,(n/2)));

所以现在你有 c = d 可能你想要:

long d = (long) (j%Math.pow(10,(n/2)));

关于java - 使用 BigInteger 的 Karatsuba 乘法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40124304/

相关文章:

Java Regex - 获取字符串中子字符串之前的所有单词

java - 无法使用 pom.xml 中的 Tycho 1.0.0 解析 "eclipse-plugin"打包类型

java - 验证输入文本中输入的文本 - Selenium

javascript - 谷歌地图算法(Ajax、Tiles 等)

Java BigInteger 表示 unsigned long

java - 大斐波那契数的最后一位快速算法

java - 在没有 Double Dispatch/Visitor 模式的情况下解决 Java 的静态方法调度

c# - 我怎样才能简化路线的描述,同时它们仍然是唯一的?

python - 计算包含给定单词一次的固定长度字符串的数量

c++ - C++ 中的大数