没有BigInteger使用的Karatsuba算法

Kha*_*han 10 java algorithm math multiplication

我一直在尝试在java中实现Karatsuba算法而不使用BigInteger.仅当整数相同且位数相同时,我的代码才适用.我没有得到正确的答案,但我得到的答案非常接近正确答案.例如,当12*12时,我得到149.我无法弄清楚我的代码有什么问题,因为我相信我做的一切都是正确的(通过本书).这是我的代码.

public static void main(String[] args) {
    long ans=karatsuba(12,12);
    System.out.println(ans);
}

private static long karatsuba(long i, long j) {
    if (i<10 || j<10){
        return i*j;
    }
    int n=getCount(i);
    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=karatsuba(a,c);
    long second=karatsuba(b,d);
    long third=karatsuba(a+b,c+d);

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

private static int getCount(long i) {
    String totalN=Long.toString(i);
    return totalN.length();
}
Run Code Online (Sandbox Code Playgroud)

编辑:

感谢Ziyao Wei,问题是用"第二"取代"第三".但是我现在有另一个问题是:

如果叫karatsuba(1234,5678),我会得到正确答案,但是当我打电话给karatsuba(5678,1234)时,我得不到正确答案.任何人都可能知道原因吗?我的更新代码是:

public static void main(String[] args) {
    //wrong answer
    long ans=karatsuba(5678,1234);
    System.out.println(ans);

    //correct answer
    long ans1=karatsuba(1234,5678);
    System.out.println(ans1);
}

private static long karatsuba(long i, long j) {
    if (i<10 || j<10){
        return i*j;
    }

    int n=getCount(i);

    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=karatsuba(a,c);
    long second=karatsuba(b,d);
    long third=karatsuba(a+b,c+d);

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

}
Run Code Online (Sandbox Code Playgroud)

更新:

我已设法将"n/2"的值四舍五入,因此它解决了问题,但是如果使用超过四位的数字,则会出现错误.这是我更新的代码:

public static void main(String[] args) {
    System.out.println(Math.round(5.00/2));

    //correct answer
    long ans=karatsuba(5678,1234);
    System.out.println(ans);

    //correct answer
    long ans1=karatsuba(1234,5678);
    System.out.println(ans1);

    //wrong answer
    long ans2=karatsuba(102456,102465);
    System.out.println(ans2);
}


private static long karatsuba(long i, long j) {
    if (i<10 || j<10){
        return i*j;
    }

    double n=Math.round(getCount(i));

    long a=(long) (i/Math.pow(10, Math.round(n/2)));
    long b=(long) (i%Math.pow(10, Math.round(n/2)));
    long c=(long) (j/Math.pow(10, Math.round(n/2)));
    long d=(long) (j%Math.pow(10, Math.round(n/2)));

    long first=karatsuba(a,c);
    long second=karatsuba(b,d);

    long third=karatsuba(a+b,c+d);

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

}

private static double getCount(long i) {
    String totalN=Long.toString(i);

    return totalN.length();
}
Run Code Online (Sandbox Code Playgroud)

如果有人在不使用BigInteger的情况下提出更大数字(超过四位数)的解决方案,请告诉我.谢谢.

zw3*_*324 5

你的公式错了.

第一个*Math.pow(10,n)+(第三个 - 第一个 - 第二个)*Math.pow(10,n/2)+ 第三个

错了,公式应该是

第一个*Math.pow(10,n)+(第三个 - 第一个 - 第二个)*Math.pow(10,n/2)+ second

维基百科:

z0 = karatsuba(low1,low2)
z1 = karatsuba((low1+high1),(low2+high2))
z2 = karatsuba(high1,high2)
return (z2*10^(m))+((z1-z2-z0)*10^(m/2))+(z0)
Run Code Online (Sandbox Code Playgroud)