Karatsuba乘法java递归代码不工作?

Karatsuba乘法java递归代码不工作?,java,algorithm,karatsuba,Java,Algorithm,Karatsuba,我试着用karatsuba乘法把两个数字相乘。我的java代码不工作。我使用字符串作为参数和参数,这样我们可以将两个n位数相乘(n是偶数)。另外,我不想使用long或biginger。请帮我找出我的代码错误 class karat{ public static String karatsuba(String first, String second){ if(first.length() <= 1 || second.length() <= 1) retu

我试着用karatsuba乘法把两个数字相乘。我的java代码不工作。我使用字符串作为参数和参数,这样我们可以将两个n位数相乘(n是偶数)。另外,我不想使用long或biginger。请帮我找出我的代码错误

class karat{

public static String karatsuba(String first, String second){

    if(first.length() <= 1 || second.length() <= 1)
        return String.valueOf(Long.parseLong(first)*Long.parseLong(second));

    String a = karatsuba(first.substring(0, first.length()/2), second.substring(0, second.length()/2));

    String b = karatsuba(first.substring(first.length() - first.length()/2, first.length()), second.substring(second.length() - second.length()/2, second.length()));

    String c = karatsuba(String.valueOf(Long.parseLong(first.substring(0, first.length()/2)) + Long.parseLong(first.substring(first.length() - first.length()/2, first.length()))), String.valueOf(Long.parseLong(second.substring(0, second.length()/2)) + Long.parseLong(second.substring(second.length() - second.length()/2, second.length()))));

    String d = String.valueOf(Long.parseLong(c) - Long.parseLong(b) - Long.parseLong(a));

    return String.valueOf(((int)Math.pow(10, first.length()))*(Long.parseLong(a)) + (((int)Math.pow(10, first.length()/2))*Long.parseLong(d)) + (Long.parseLong(c)));
}

public static void main(String[] args){
        String result = karatsuba("1234", "5678");
        System.out.println(result); }
}
克拉级{
公共静态字符串karatsuba(第一个字符串,第二个字符串){

if(first.length()有趣的算法。一个错误在

return String.valueOf(((int)Math.pow(10, first.length()))*(Long.parseLong(a)) + (((int)Math.pow(10, first.length()/2))*Long.parseLong(d)) + (Long.parseLong(c)));
最后,它应该是
Long.parseLong(b)
,而不是
Long.parseLong(c)

在中间计算中,两个字符串的长度可能不同,这也不能正常工作

请允许一些注释来改进实现。使用字符串的想法似乎允许使用大数字,但随后您引入了
Long.parseLong()
(int)Math.pow(10,first.length())
,将您限制在
Long
int
范围内

如果你真的想做大数字,写下你自己的基于字符串的加法和十次方乘法(通过加上一些零,这个乘法很简单)


此外,尽量避免使用像a、b、c或d这样的名称-很容易忘记它们的意思,这是您最初的错误。例如,中的名称稍微好一点(使用z0、z1和z2),但仍然不完美…

首先,我试着看一下您的代码,它会让程序员迷失方向,在我们进入解决方案之前做了一些事情

一般建议。像您这样将字符串转换为值并来回转换是不好的做法,它不能像这样工作。我也尝试过调试您的代码,这只是一个恶性循环

因此,我将从检查值长度和最大值开始

如果其中一个值的长度小于2,则表示每件事情的长度小于10,则执行乘法,否则执行karatsuba递归算法

以下是解决方案:

public static long karatsuba(long num1, long num2) {

    int m = Math.max(
            String.valueOf(num1).length(),
            String.valueOf(num2).length()
    );

    if (m < 2)
        return num1 * num2;

    m = (m / 2) + (m % 2);

    long b = num1 >> m;
    long a = num1 - (b << m);
    long d = num2 >> m;
    long c = num2 - (d << m);

    long ac = karatsuba(a, c);
    long bd = karatsuba(b, d);
    long abcd = karatsuba(a + b, c + d);

    return ac + (abcd - ac - bd << m) + (bd << 2 * m);
}
输出将是

9
7006652
83810205

它比你严格的代码更简单。顺便说一句,这个解决方案的灵感来自于wiki和这本书。

试着写下与
Math.pow(10,length/2)
(和
Math.pow(10,2*(length/2))
)相乘意味着什么。手工做几个例子(特别是不同/非幂-of-2长度的例子)在纸上一切都很好。例如,我通过了22和22。输出是496,应该是484。我不知道怎么了。您(不必要)使用
String.valueOf(s.substring())
,反复确定输入的相同部分(例如
第一个.substring(0,第一个.length()/2)
)不要给那些部分命名:这会使你的代码很难理解和争论。选择一个易于访问的Karatsuba算法表示作为参考,并相应地为这些部分命名变量。大多数都带有一个(微小的)示例:使用调试器跟踪代码的步骤。调整此处显示的代码并识别引用。如果仍然无法发现“错误”(还有更多错误),请准确描述您发现自己陷入困境的地方。您的问题与此非常相似:感谢您的帮助。按照您的建议进行更改后,程序仍在运行,但1234*5678上的输出仍然错误。出了什么问题?正如我所说,“在中间计算中,两个字符串的长度可能不同。这也不能正常工作。”遵循程序流程(通过调试器或插入System.out.println()调用),然后您将看到您的
karatusuba
方法返回错误结果的情况。仔细一步一步地分析该情况,您将看到出了什么问题。还有一个提示:不要在一行代码中执行太多操作-引入中间变量,这将使调试更容易。谢谢。从下一次开始,我将始终关注w编写代码,便于他人阅读。如果我不使用字符串,我如何在长范围内将大于数字的数字相乘。我将字符串转换为长,反之亦然,以便对字符串进行计算,因为我不能将两个字符串相乘。我的主要目标是将n个数字相乘,这可能大于当前的数字从长远来看。这叫做大数字。看看我在答案中加入链接的类,这正是你要找的,如果你认为答案有帮助,请检查答案谢谢你,梅瑟姆。我没有办法使用字符串吗?它可能和你以前一样,然后你需要前后转换,记住你不能使用string可强制任何类型的最大值,例如整数最大值为2147483647。您不能使用大于此数字的字符串并将其转换为int。这对于任何类型都有效,您需要检查要使用的数字大小规范。
9
7006652
83810205