我试图使用karatsuba乘法乘以两个数字。我的java代码不起作用。我已经使用字符串作为参数和参数,这样我们就可以将两个n位数相乘(n是偶数)。另外,我不想使用long或BigInteger。请帮我弄清楚我的代码错误。
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); }
}
您还可以优化我的代码。
为乘法传递的数字 - 1234和5678
输出为 - 6655870(不正确)
输出应为 - 7006652(正确)
谢谢
答案 0 :(得分:1)
首先,我试着看一下你的代码,它让程序员迷失方向,在我们进入解决方案之前就做了一些事情。
一般建议。将字符串转换为值并像往返一样前后转换并不是一个好习惯,它不会像这样工作。我也试过调试你的代码,它只是魔鬼圈。
所以我先从检查值长度和最大值开始。
如果其中一个值小于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);
}
一些测试;
public static void main(String[] args) {
System.out.println(karatsuba(1, 9));
System.out.println(karatsuba(1234, 5678));
System.out.println(karatsuba(12345, 6789));
}
输出为
9
7006652
83810205
答案 1 :(得分:0)
有趣的算法。
中有一个错误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
范围内。
如果你真的想要做大数字,那就写下你自己的基于字符串的加法和10次幂乘法(通过附加一些零来实现这一点很简单)。
并且,尽量避免像a,b,c或d这样的名字 - 它太容易忘记它们的意思,就像你原来的错误一样。例如。来自Wikipedia的名字有点好(使用z0,z1和z2),但仍然不完美...