0

This code is not passing all the test cases, can somebody help? I only pass the straight forward test then it loses precision.

import math
import unittest


class IntegerMultiplier:

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

        x = str(x)
        y = str(y)

        m_max = min(len(x), len(y))
        x = x.rjust(m_max, '0')
        y = y.rjust(m_max, '0')

        m = math.floor(m_max / 2)

        x_high = int(x[:m])
        x_low = int(x[m:])

        y_high = int(y[:m])
        y_low = int(y[m:])

        z1 = self.multiply(x_high, y_high)
        z2 = self.multiply(x_low, y_low)
        z3 = self.multiply((x_low + x_high), (y_low + y_high))
        z4 = z3 - z1 - z2

        return z1 * (10 ** m_max) + z4 * (10 ** m) + z2


class TestIntegerMultiplier(unittest.TestCase):

    def test_easy_cases(self):
        integerMultiplier = IntegerMultiplier()

        case2 = integerMultiplier.multiply(2, 2)
        self.assertEqual(case2, 4)

        case3 = integerMultiplier.multiply(2, 20000)
        self.assertEqual(case3, 40000)

        case4 = integerMultiplier.multiply(2000, 2000)
        self.assertEqual(case4, 4000000)

    def test_normal_cases(self):
        intergerMultiplier = IntegerMultiplier()

        case1 = intergerMultiplier.multiply(1234, 5678)
        self.assertEqual(case1, 7006652)

if __name__ == '__main__':
    unittest.main()

for the first test case, 'test_easy_cases' all are passing for the other two cases, I get error e.g. AssertionError: 6592652 != 7006652

3
  • 1
    m_max = min(len(x), len(y)) After answering, I think I know what you wanted here - it urgently needs a code comment, as it looks plain wrong without. Commented Jul 21, 2019 at 10:27
  • 1
    You should add at least one non-trivial asymmetric test case like 123, 98. Commented Jul 21, 2019 at 10:36
  • 1
    Two suggestions how to approach this: Firstly, find a small testcase (can yours get any smaller?) that triggers the issue. Then, use a debugger to step through the code and to inspect when exactly its state is not what you expect. Commented Jul 21, 2019 at 10:47

1 Answer 1

1

In choosing m, you choose a base for all following decompositions and compositions. I recommend one with a representation of length about the average of the factors' lengths.
I have "no" idea why time and again implementing Karatsuba multiplication is attempted using operations on decimal digits - there are two places you need to re-inspect:

  • when splitting a factor f into high and low, low needs to be f mod m, high f // m
  • in the composition (last expression in IntegerMultiplier.multiply()), you need to stick with m (and 2×m) - using m_max is wrong every time m_max isn't even.
Sign up to request clarification or add additional context in comments.

1 Comment

When slicing in Python, a negative number means "from the right end".

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.