1

I am trying to do the Karatsuba multiplication here. The below code works for numbers with two digits (eg 78 * 34) but gives wrong results for numbers with digits greater than 2 (eg 5678 * 1234). I have attached the debugging logs. After a certain point the calculations are wrong. Can someone take a look and tell me if my understanding of the algorithm is incorrect?

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;
}

Debug Logs:

After getting the result of 2652, the next calculations are wrong.

enter image description here

Haritha
  • 391
  • 1
  • 9
  • 1
    Have you stepped through the code in your IDE debugger to see where it deviates from what you expect? SO is not a debugging service, you need to show you have made an effort. Please take the [tour], visit the [help] and read [Ask] to learn how to use this site effectively. Also read [Why is “Can someone help me?” not an actual question?](http://meta.stackoverflow.com/q/284236/18157) – Jim Garrison Apr 17 '21 at 00:22
  • `wrong results for numbers with digits greater than 2` every digit in `78 * 34` is greater than two. (Granted, two in the product are not.) – greybeard Apr 17 '21 at 13:24
  • @greybeard Not sure if you're being sarcastic or genuinely misunderstood; however, I think it's quite clear that the OP means "more than 2 digits." – Adrian Mole Apr 17 '21 at 19:57
  • @JimGarrison I mean, that was a combination of misunderstanding the algorithm and a slight rounding error that only by debugging is hard to find. – Kaplan Apr 19 '21 at 09:46
  • Edit - I have added the debug logs and tried to frame my question differently so it helps others. Kaplan's helped me in understanding where I was going wrong. Thanks. – Haritha Apr 19 '21 at 16:51
  • It might help if you quoted an algorithmic description or hyperlinked an accessible one - up to [revision 3](https://stackoverflow.com/revisions/67133180/3), it is very difficult to tell what your picture of the algorithm is just seeing uncommented source code. What are all those values `m` and `n` can have, what is `dbby2` if `n` is odd? Why string operations on a digit rendition in one place and arithmetic with limited precision results of a transcendental function in another? – greybeard Apr 19 '21 at 20:41

1 Answers1

2

an obvious mistake is, that the multipliers are incorrectly padded with zeros

if ((str1.length() & 1) == 1) {
    str1 = "0" + str1;
}
while (str2.length() < str1.length()) {
    str2 = "0" + str2;
}

and here is the 2nd mistake:
rounding error in the exponent because of the wrong
pow function

step1 = step1.multiply(BigInteger.valueOf(10L).pow(n));
step4 = step4.multiply(BigInteger.valueOf(10L).pow(n/2));

5678 * 1234 = 7006652
84232332233 * 1532664392 = 129099896268632947336
before padding with zeros: the length of str1 must always be greater than or equal to the length of str2

Kaplan
  • 2,572
  • 13
  • 14