|
| 1 | +import random |
| 2 | +from math import ceil |
| 3 | +from math import log10 |
| 4 | + |
| 5 | + |
| 6 | +def get_digits(n): |
| 7 | + if n > 0: |
| 8 | + digits = int(log10(n)) + 1 |
| 9 | + elif n == 0: |
| 10 | + digits = 1 |
| 11 | + else: |
| 12 | + digits = int(log10(-n)) + 2 |
| 13 | + return digits |
| 14 | + |
| 15 | + |
| 16 | +def karatsuba(x, y): |
| 17 | + # the base case for recursion |
| 18 | + if x < 10 and y < 10: |
| 19 | + return x * y |
| 20 | + |
| 21 | + # n is the number of digits in the highest input number |
| 22 | + n = max(get_digits(x), get_digits(y)) |
| 23 | + |
| 24 | + n_2 = int(ceil(n / 2.0)) |
| 25 | + n = n if n % 2 == 0 else n + 1 |
| 26 | + |
| 27 | + # split the input numbers |
| 28 | + a, b = divmod(x, 10 ** n_2) |
| 29 | + c, d = divmod(y, 10 ** n_2) |
| 30 | + |
| 31 | + # applying the recursive steps |
| 32 | + ac = karatsuba(a, c) |
| 33 | + bd = karatsuba(b, d) |
| 34 | + ad_bc = karatsuba((a + b), (c + d)) - ac - bd |
| 35 | + |
| 36 | + # performs the multiplication |
| 37 | + z2 = (10 ** n) * ac |
| 38 | + z1 = (10 ** n_2) * ad_bc |
| 39 | + z0 = bd |
| 40 | + return z2 + z1 + z0 |
| 41 | + |
| 42 | + |
| 43 | +def test(): |
| 44 | + for i in range(1000): |
| 45 | + x = random.randint(1, 10**5) |
| 46 | + y = random.randint(1, 10**5) |
| 47 | + expected = x*y |
| 48 | + result = karatsuba(x, y) |
| 49 | + if result != expected: |
| 50 | + return print("failed") |
| 51 | + return print("ok") |
| 52 | + |
| 53 | + |
| 54 | +if __name__ == '__main__': |
| 55 | + test() |
0 commit comments