1

Beginner here. I've spent most of the day working on the Karatsuba Algorithm just because I thought it would be fruitful. I've seen similar questions on here, but they are in other languages and seem strangely complex. The following is my code. The minute it hits the recursive call to ac, it just keeps on recursing. It's as if it never hits the base case. If anyone could be so kind as to offer some insight as to where things are going wrong, it would be greatly appreciated. For this code, you should assume I'm multiplying 2, base-10, four-digit numbers.

def karatsuba(x, y):
    if len(str(x)) == 1 or len(str(y)) == 1:
        return (x * y)

    else:
        n = (max(len(str(x)), len(str(y))))

        a = x / 10**(n / 2)
        b = x % 10**(n / 2)
        c = y / 10**(n / 2)
        d = y % 10**(n / 2)

        ac = karatsuba(a, c)
        ad = karatsuba(a, d)
        bc = karatsuba(b, c)
        bd = karatsuba(b, d)

        product = (10**n*(ac) + 10**(n/2)*(ad + bc) + bd)

        return product

print (karatsuba(1234, 5678))
Ryan
  • 1,312
  • 3
  • 20
  • 40
  • the `len` of number will never be `<1` - there is always at least 1 digit even if it is a `0` assume you meant `==1`. If that is the case, any reason not to just test if they are `<10` instead of converting to a `str`? – AChampion Oct 08 '16 at 02:32
  • @AChampion -- Thanks for the reply. Very good catch! I tried both methods. The == 1 approach left me with the same infinite recursion. The < 10 approach (with no typecasting to string) left me with a *different* infinite recursion on the "bc" line. The plot thickens. Thanks again! – Ryan Oct 08 '16 at 02:46
  • Is the issue indeterminate? I.e. are you finding different results each time your run it? – sakurashinken Oct 08 '16 at 03:25
  • @sakurashinken I wish I were getting some result. I use IDLE for python, and I just get an endless stream of error pointing to a recursive line, right now it's ac. When I insert print statements, I saw a lot of decimalised values for a & c, that were unexpected. – Ryan Oct 08 '16 at 03:28
  • Assuming you are using python3. Use integer division `//` or you will introduce floats and cause issues. Tested with integer division and it works fine, though you can eliminate one of the recursive calls and much quicker would be operating in binary vs. decimal. – AChampion Oct 08 '16 at 03:42
  • I too only ran into issues with floats. It seems that integer devision is the issue. – sakurashinken Oct 08 '16 at 03:48
  • The algorithm shown is what Андрей Николаевич Колмогоров (Andrey Nikolaevich Kolmogorov) presented to his students, including Анато́лий Алексе́евич Карацу́ба (Anatoly Alexeevitch Karatsuba), claiming the work to multiply numbers of "length _n_" grew with _n²_. Karatsuba walked up to him and presented [a multiplication algorithm significantly faster for large numbers](https://en.wikipedia.org/wiki/Karatsuba_algorithm). (See [AChampion's answer](http://stackoverflow.com/a/39928519/3789665), too.) – greybeard Oct 08 '16 at 05:20

2 Answers2

3

Just fixing your code with integer divisions made it work correctly but here's a slight different version using 3 recursive calls (in base 10):

def karatsuba(x, y):
    if x < 10 or y < 10:
        return x * y

    n = max(len(str(x)), len(str(y))) // 2
    p = 10**n

    a, b = divmod(x, p)
    c, d = divmod(y, p)

    ac = karatsuba(a, c)
    bd = karatsuba(b, d)
    abcd = karatsuba(a+b, c+d) - ac - bd

    return (ac*p + abcd)*p + bd

But it is much faster operating in binary and using bit-twiddling:

def karatsuba(x, y):
    if x < 16 or y < 16:
        return x * y

    n = max(x.bit_length(), y.bit_length()) // 2
    mask = (1 << n) - 1

    a, b = x >> n, x & mask
    c, d = y >> n, y & mask

    ac = karatsuba(a, c)
    bd = karatsuba(b, d)
    abcd = karatsuba(a+b, c+d) - ac - bd

    return (((ac << n) + abcd) << n) + bd
AChampion
  • 29,683
  • 4
  • 59
  • 75
1

Do you want integer division? In this case, you should use:

a = x // 10 ** (n / 2)

and

c = y // 10 ** (n / 2)

Otherwise, your program will be feeding through decimals to your function which I assume is not intended.

I'm also a beginner, feel free to correct me.

boboquack
  • 249
  • 5
  • 15
  • Many thanks for the reply! It made sense, so I gave it a shot. Unfortunately, the infinite recursion issue moved from the computation of ac to the recursive call for bd. Thanks again! – Ryan Oct 08 '16 at 03:21
  • 1
    @RyanD. You need to fix `n//2` too - assuming you are using Python3. Which you also have in the final `product` calculation. – AChampion Oct 08 '16 at 03:41