【发布时间】:2021-08-23 12:40:54
【问题描述】:
我正在努力使用字符串为我的 Karatsuba 乘法获得正确的输出。 我输入的数字格式为:int1 int2 base,其中 int1 和 int2 是要相乘的数字,base 是数字底数。
我的输出格式为 add mult,其中 add 代表 int1 和 int2 的“School Method Addition”,mult 代表 Karatsuba 乘法。
对于输入:
1231000323012031333233201313312322110321130022201222133322033312000313333113222010300133031211311 10203302031023112301210030203002033323 4
我应该得到输出:
1231000323012031333233201313312322110321130022201222133322110121303011022232123220331002033311300
490306232475117580392628428529303475424922697851904379576867313243824589283681700912220831308362948505562812188832489817917769878090
我不确定出了什么问题,任何帮助将不胜感激。
下面是我的代码:
// The main function that adds two bit sequences and returns the addition
string add_strings(string a, string b){
string result ; // To store the sum bits
// make the lengths same before adding
int length = max(a.length(), b.length()) ;
while (a.length() < length) a.insert(0, "0") ;
while (b.length() < length) b.insert(0, "0") ;
// Initialize carry
int carry = 0 ;
// Add all bits one by one
for (int i = length - 1 ; i > -1 ; i--)
{
int aBit = a[i] - '0' ;
int bBit = b[i] - '0' ;
// Boolean expression for sum of 3 bits
int sum = aBit + bBit + carry ;
// Update carry
carry = sum / base ;
// Update sum for string insertion
sum = sum % base ;
// Update sum result
result.insert(0, to_string(sum)) ;
}
// if overflow, then add the carry
if (carry) result.insert(0, to_string(carry)) ;
return result.erase(0, min(result.find_first_not_of('0'), result.size() - 1)) ;
}
// Function for find difference of larger numbers
string sub_strings(string a, string b, int base)
{
// Ensure the first string is bigger than the second
// Therefore no negative cases, no carry needed
int comp = a.compare(b) ;
if (comp < 0) swap(a, b) ;
// Make the lengths same before subtracting
int length = max(a.length(), b.length()) ;
while (a.length() < length) a.insert(0, "0") ;
while (b.length() < length) b.insert(0, "0") ;
// Initialise result string
string result = "";
int diff, carry ;
// Subtraction
for (int i = length - 1; i > -1; i--) {
// Find difference of each digit
int aBit = a[i] - '0' ;
int bBit = b[i] - '0' ;
diff = (aBit - bBit) / base ;
result.insert(0, to_string(diff)) ;
}
// reverse resultant string
reverse(result.begin(), result.end());
return result.erase(0, min(result.find_first_not_of('0'), result.size() - 1)) ;
}
更新: 我添加了一个左移函数以确保所有内容都乘以基数:
void leftShift(string &ab, int k){
reverse(ab.begin(), ab.begin() + 1) ;
reverse(ab.begin() + 1, ab.end()) ;
reverse(ab.begin(), ab.end()) ;
}
这是我更新的 Karatsuba:
string Karatsuba(string a, string b, int base){
// Base cases
int length = max(a.length(), b.length());
if (length == 0) return 0 ;
if (length == 1) return to_string((a[0] - '0')*(b[0] - '0')) ;
// Add leading zeros to ensure numbers are the same size
while (a.length() < length) a.insert(0, "0") ;
while (b.length() < length) b.insert(0, "0") ;
// Split a into (a0, a1) and b into (b0, b1)
int k = length / 2 ;
int upper = length - k ;
// convert the above vectors to strings for multiplication
// need separate for loops to prevent out of range errors
string a0 = a.substr(k) ;
string a1 = a.substr(0, upper) ;
string b0 = b.substr(k) ;
string b1 = b.substr(0, upper) ;
// Compute the three products
// p0 = a0b0, p1 = (a1+a0)*(b1+b0), p2 = a1b1
string p0 = Karatsuba(a0, b0, base) ;
string p1 = Karatsuba(add_strings(a1, a0, base), add_strings(b1, b0, base), base) ;
string p2 = Karatsuba(a1, b1, base) ;
//ab = p2 * (pow(base, 2*k)) + (p1 - (p2 + p0)) * pow(base, k) + p0
// term1 = p2 * (pow(base, 2*k))
// term2 = (p1 - (p2 + p0)) * pow(base, k)
string term2 = sub_strings(add_strings(p2, p0, base), p1, base) ;
leftShift(p2, k) ;
leftShift(p2, k) ;
leftShift(term2, k) ;
// term3 = p0
// Add leading zeros
for (int i = 0; i < upper; i++) p0.append("0") ;
for (int i = 0; i < upper; i++) term2.append("0") ;
string result = add_strings(add_strings(p2, p0, base), term2, base) ;
return result.erase(0, min(result.find_first_not_of('0'), result.size() - 1));
}
【问题讨论】:
-
c 和 c++ 是不同的语言,请不要同时标记两者,除非您实际上同时使用这两种语言。你的代码的输出是什么?您是否尝试过使用调试器?
-
我建议您在调试阶段使用 6 字节字符串,而不是 97 字节字符串。然后您可以手动进行计算并将它们与您的代码结果进行比较。
-
当输入为 base 4 时,为什么预期的输出不在 base 4 中?为什么你的代码有一堆
/ 10和% 10表明它特定于基数 10? -
有很多代码需要调试和审查。我看到的第一个气味是在 floor 和 ceil 中使用浮点。
int k = length/2;已经四舍五入了,int upper = length - k;会给你剩下的,而不用求助于浮点数学。 -
查看您的代码,您对
base根本没有做任何事情。