Java 中的 Karatsuba 乘法
Karatsuba multiplication in Java
我想在这里做 Karatsuba 乘法。下面的代码适用于具有两位数的数字(例如 78 * 34),但对于数字大于 2 的数字(例如 5678 * 1234)给出错误的结果。我附上了调试日志。在某一点之后,计算是错误的。谁能帮我看看是不是我对算法的理解有误?
static BigInteger karatsuba(BigInteger no1, BigInteger no2){
BigInteger result = null;
//Both numbers less than 10
if(no1.compareTo(new BigInteger("9")) != 1 && no2.compareTo(new BigInteger("9")) != 1 ){
return no1.multiply(no2);
}
String str1 = no1.toString();
String str2 = no2.toString();
if(str1.length() ==1) {
str1 = "0" + str1;
}
if(str2.length() ==1) {
str2 = "0" + str2;
}
int m = str1.length()/2;
String a = str1.substring(0,m);
String b = str1.substring(m,str1.length());
m = str2.length()/2;
String c = str2.substring(0,m);
String d = str2.substring(m,str2.length());
BigInteger step1 = karatsuba(new BigInteger(a),new BigInteger(c));
BigInteger step2 = karatsuba(new BigInteger(b),new BigInteger(d));
BigInteger step3 = karatsuba(new BigInteger(a).add(new BigInteger(b)),new BigInteger(d).add(new BigInteger(c)));
BigInteger step4 = step3.subtract(step2).subtract(step1);
int n = str1.length() > str2.length() ? str1.length() : str2.length();
double db = Math.pow(10,n);
double dbby2 = Math.pow(10,(n/2));
step1 = step1.multiply(BigDecimal.valueOf(db).toBigInteger());
step4 = step4.multiply(BigDecimal.valueOf(dbby2).toBigInteger());
result = step1.add(step4).add(step2);
return result;
}
调试日志:
得到2652的结果后,接下来的计算是错误的
一个明显的错误是,乘数被错误地填充了零
if ((str1.length() & 1) == 1) {
str1 = "0" + str1;
}
while (str2.length() < str1.length()) {
str2 = "0" + str2;
}
这是第二个错误:
由于错误 pow
函数[=27,导致指数出现舍入误差=]
step1 = step1.multiply(BigInteger.valueOf(10L).pow(n));
step4 = step4.multiply(BigInteger.valueOf(10L).pow(n/2));
5678 * 1234 = 7006652
84232332233 * 1532664392 = 129099896268632947336
用零填充之前:str1
的长度必须始终大于或等于 str2
的长度
我想在这里做 Karatsuba 乘法。下面的代码适用于具有两位数的数字(例如 78 * 34),但对于数字大于 2 的数字(例如 5678 * 1234)给出错误的结果。我附上了调试日志。在某一点之后,计算是错误的。谁能帮我看看是不是我对算法的理解有误?
static BigInteger karatsuba(BigInteger no1, BigInteger no2){
BigInteger result = null;
//Both numbers less than 10
if(no1.compareTo(new BigInteger("9")) != 1 && no2.compareTo(new BigInteger("9")) != 1 ){
return no1.multiply(no2);
}
String str1 = no1.toString();
String str2 = no2.toString();
if(str1.length() ==1) {
str1 = "0" + str1;
}
if(str2.length() ==1) {
str2 = "0" + str2;
}
int m = str1.length()/2;
String a = str1.substring(0,m);
String b = str1.substring(m,str1.length());
m = str2.length()/2;
String c = str2.substring(0,m);
String d = str2.substring(m,str2.length());
BigInteger step1 = karatsuba(new BigInteger(a),new BigInteger(c));
BigInteger step2 = karatsuba(new BigInteger(b),new BigInteger(d));
BigInteger step3 = karatsuba(new BigInteger(a).add(new BigInteger(b)),new BigInteger(d).add(new BigInteger(c)));
BigInteger step4 = step3.subtract(step2).subtract(step1);
int n = str1.length() > str2.length() ? str1.length() : str2.length();
double db = Math.pow(10,n);
double dbby2 = Math.pow(10,(n/2));
step1 = step1.multiply(BigDecimal.valueOf(db).toBigInteger());
step4 = step4.multiply(BigDecimal.valueOf(dbby2).toBigInteger());
result = step1.add(step4).add(step2);
return result;
}
调试日志:
得到2652的结果后,接下来的计算是错误的
一个明显的错误是,乘数被错误地填充了零
if ((str1.length() & 1) == 1) {
str1 = "0" + str1;
}
while (str2.length() < str1.length()) {
str2 = "0" + str2;
}
这是第二个错误:
由于错误 pow
函数[=27,导致指数出现舍入误差=]
step1 = step1.multiply(BigInteger.valueOf(10L).pow(n));
step4 = step4.multiply(BigInteger.valueOf(10L).pow(n/2));
5678 * 1234 = 7006652
84232332233 * 1532664392 = 129099896268632947336
用零填充之前:str1
的长度必须始终大于或等于 str2