I1,I2
,和一个基数B
,运用卡拉楚巴算法让两个数字相乘得到乘积并输出。(a1*b1)*base^2k+[(a0+a1)(b0+b1) - a1*b1 - a0*b0]*base^k + a0*b0
因此我多加了一个加法的方法,一个减法的方法,一个进制转换的方法,来实现卡拉楚巴算法
我测试后发现我的加法和减法是没问题的,输出结果正确,只有karatsuba方法里有错误
#include
#include
#include
#include
using namespace std;
//加法:
string schoolAdd(string num1, string num2, int base) {
string result = "";
int carry = 0;
//when I1 and I2 all empty, break the loop
while (!num1.empty() || !num2.empty() || carry > 0) {
int digit1 = num1.empty() ? 0 : num1.back() - '0'; // 取最后的位
int digit2 = num2.empty() ? 0 : num2.back() - '0';
int sum = digit1 + digit2 + carry;
carry = sum / base;
sum = sum % base;
result.push_back(sum + '0');
if (!num1.empty()) num1.pop_back();
if (!num2.empty()) num2.pop_back();
}
reverse(result.begin(), result.end());
return result;
}
// 转换进制
string convert(int num, int base, string result){
if (num < base){
return to_string(num);
}else{
int c = num % base; //取余数
num = num / base;
result = convert(num, base, result);
result = result + to_string(c);
}
return result;
}
//减法
string substraction(string a, string b, int base)
{
int len1 = a.length();
int len2 = b.length();
if (len1 < len2){
a.insert(0, len2 - len1, '0');
}
else{
b.insert(0, len1 - len2, '0');
}
string res;
int carry = 0;
for (int i = a.length() - 1; i >= 0; i--) {
int sub = (a[i] - '0') - (b[i] - '0') - carry;
if (sub < 0) {
sub += base;
carry = 1;
}
else {
carry = 0;
}
res.insert(0, to_string(sub));
}
//去掉前导0
while (res.size() > 1 && res[0] == '0'){
res.erase(0, 1);
}
return res;
}
//Q2, 卡拉楚巴算法
string karatsuba(string I1, string I2, int base){
int I1size = I1.size();
int I2size = I2.size();
if (I1size < I2size){ //补齐位数
for (int i = 0; i < I2size - I1size; i++){
I1 = '0' + I1;
}
}else{
for (int i = 0; i < I1size - I2size; i++){
I2 = '0' + I2;
}
}
if (I1.size() == 1 && I2.size() == 1){
int num1 = I1[0] - '0';
int num2 = I2[0] - '0';
int product = num1 * num2;
string result = "";
result = convert(product, base, result); //转换位基数base的数字
return result;
}else{
//先分成两部分
//I1
string a1 = "";
string a0 = "";
int mid = I1.size() / 2;
for (int i = 0; i < mid; i++) {
a1 += I1[i];
}
for (int i = mid; i < (int)I1.size(); i++) {
a0 += I1[i];
}
// I2
string b1 = "";
string b0 = "";
for (int i = 0; i < mid; i++) {
b1 += I2[i];
}
for (int i = mid; i < (int)I2.size(); i++) {
b0 += I2[i];
}
int k = I1.size() - mid;
// (a1*b1)*base^2k+[(a0+a1)(b0+b1) - a1*b1 - a0*b0]*base^k + a0*b0
string a1b1 = karatsuba(a1, b1,base); //a1*b1
string a1a0 = schoolAdd(a1, a0, base); //a0+a1
string b1b0 = schoolAdd(b1, b0, base); //b0+b1
string a0b0 = karatsuba(a0, b0, base); //a0*b0
string p1 = a1b1;
p1.insert(p1.end(), 2*k, '0');
string p2 = karatsuba(a1a0, b1b0, base);
string p3 = schoolAdd(a1b1, a0b0,base);
string sub = substraction(p2, p3, base);
sub.insert(0, k, '0');
string p4 = a0b0;
string result = p1;
result = schoolAdd(result,sub,base);
result = schoolAdd(result,p4,base);
return result;
}
return "0";
}
int main() {
int B;
string I1, I2;
cin >> I1 >> I2 >> B;
cout << schoolAdd(I1, I2, B) <<" " << substraction(I1,I2, B)<<" " << karatsuba(I1,I2,B)<< endl;
return 0;
}
10000000 1 10
我的输出:10000001 9999999 000000000000001
我想要的结果应该是:10000001 9999999 10000001
请问有人知道我思路哪里错了吗
https://www.cnblogs.com/tigerisland/p/7564172.html
参考GPT和自己的思路:
经过仔细研究你的代码,我发现你在卡拉楚巴算法的实现过程中有一个小错误:在计算p2
时,你应该将其乘以base^k
而不是base^(2*k)
。
这是你的错误代码:
string p2 = karatsuba(a1a0, b1b0, base);
这是你应该修改后的正确代码:
string p2 = karatsuba(a1a0, b1b0, base);
p2.insert(p2.begin(), k, '0');
这样做的原因是,在原来的卡拉楚巴算法中,我们需要将 [(a0 + a1)(b0 + b1) - a0b0 - a1b1]
结果中的a0b0
和 a1b1
项清除,而避免使用额外的传递参数或变量,我们在这里使用了字符串拼接的方式,因此需要注意位数的保持。
所以你只需要替换代码中的部分:
// (a1*b1)*base^2k+[(a0+a1)(b0+b1) - a1*b1 - a0*b0]*base^k + a0*b0
string a1b1 = karatsuba(a1, b1,base); //a1*b1
string a1a0 = schoolAdd(a1, a0, base); //a0+a1
string b1b0 = schoolAdd(b1, b0, base); //b0+b1
string a0b0 = karatsuba(a0, b0, base); //a0*b0
string p1 = a1b1;
p1.insert(p1.end(), 2*k, '0');
string p2 = karatsuba(a1a0, b1b0, base);
string p3 = schoolAdd(a1b1, a0b0,base);
string sub = substraction(p2, p3, base);
sub.insert(0, k, '0'); // <-- Insert the k here!
string p4 = a0b0;
string result = p1;
result = schoolAdd(result,sub,base);
result = schoolAdd(result,p4,base);
return result;
我相信你会成功地运行你的程序并得到正确的答案。