lundi 23 août 2021

Karatsuba Multiplication with Strings C++

I am struggling to get the correct output for my Karatsuba multiplication using strings. I am inputting numbers in the format: int1 int2 base, where int1 and int2 are the numbers to be multiplied, and base is the numerical base.

My output is in the format add mult, where add represents the "School Method Addition" of int1 and int2 and mult represents the Karatsuba multiplication.

For INPUT:

1231000323012031333233201313312322110321130022201222133322033312000313333113222010300133031211311 10203302031023112301210030203002033323 4

I should get the OUTPUT:

1231000323012031333233201313312322110321130022201222133322110121303011022232123220331002033311300 
490306232475117580392628428529303475424922697851904379576867313243824589283681700912220831308362948505562812188832489817917769878090

I am unsure what's going wrong, any help would be appreciated.

Below is my code:

// 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 / 10 ;

        // Update sum for string insertion
        sum = sum % 10 ;
 
        // 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) {

    // 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 ;
 
    int carry = 0;
 
    // Subtraction
    for (int i = length - 1; i > -1; i--) {
 
        // Find difference of each digit
        diff = (a[i] - '0') - (b[i] - '0') - carry ;

        if (diff >= 0) result.insert(0, to_string(diff)) ;
            
        else {
            int j = i - 1 ;
            while (j >= 0) {
                a[j] = ((a[j] - '0') - 1) % 10 + '0' ;
                if (a[j] != '9') break ;
                else j-- ;   
            }
            result.insert(0, to_string(diff + 10)) ;
        }
 
     }
 
    // reverse resultant string
    reverse(result.begin(), result.end());
 
    return result.erase(0, min(result.find_first_not_of('0'), result.size() - 1)) ; 
}

// Need this function for strings greater than 3 in length

string Karatsuba(string a, string b, int base){

    // Pad out each recursive call to ensure they are the same size
    int length = max(a.length(), b.length());
    while (a.length() < length) a.insert(0, "0") ;
    while (b.length() < length) b.insert(0, "0") ;

    // Initialise strings
    string return_karat = "" ;
 
    // Base cases
    if (length == 0) return 0 ;
    if (length == 1) return to_string((a[0] - '0')*(b[0] - '0')) ;

    // Split a into (a0, a1) and b into (b0, b1)
    int k = floor(length / 2) ;
    int upper = ceil(length / 2) ;

    // convert the above vectors to strings for multiplication
    // need separate for loops to prevent out of range errors
    string a0 = a.substr(0, k) ;
    string a1 = a.substr(k, upper) ;
    string b0 = b.substr(0, k) ;
    string b1 = b.substr(k, 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), add_strings(b1, b0), base) ;
    string p2 = Karatsuba(a1, b1, base) ;

    //ab = p2 * (pow(base, 2*k)) + (p1 - (p2 + p0)) * pow(base, k) + p0
    // string term1 = p2 * (pow(base, 2*k))
    string term2 = sub_strings(add_strings(p0, p2), p1) ;
    // string term3 = p0

    for (int i = 0; i < 2 * (length - k); i++) p0.append("0") ;
    for (int i = 0; i < length - k; i++) term2.append("0") ;
        
    string result = add_strings(add_strings(p2, p0), term2) ;

    return result.erase(0, min(result.find_first_not_of('0'), result.size() - 1));
}

Aucun commentaire:

Enregistrer un commentaire