2
\$\begingroup\$

Implement addition, subtraction, division and multiplication of given numbers of different base and provide result in desired base:

Example:

n1,b1 = 1010, 2

n2,b2 = 100, 10

desired_base = 9

addition(n1,b1,n2,b2,desired_base) = 22

subtraction(n1,b1,n2,b2,desired_base) = 0

multiplication(n1,b1,n2,b2,desired_base) = 121

I have written this code, but How to improve its complexity?

global dict_base, dict_reverse
dict_base = {'0': 0, '1':1, '2':2, '3':3, '4':4, '5':5, '6':6,'7':7,'8':8, '9':9, 'A':10, 'B':11, 'C':12, 'D':13, 'E':14, 'F':15, 'G':16, 'H':17}
dict_reverse = {v: k for k, v in dict_base.iteritems()}
def convert_to_base_10(num_str, base):
    global dict_base
    k = 1
    ans = 0
    for char in num_str[::-1]:
        ans += dict_base[char] * k
        k = k * base
    return int(ans)    

def convert_from_base_10(num, des_base):
    global dict_reverse
    ans = []
    neg_flag = False
    import pdb; pdb.set_trace()
    if num < 0:
        neg_flag = True
        num = num * (-1)
    while num>0:
        ans.append(dict_reverse[num % des_base])
        num = num / des_base
    if neg_flag:
        return '-'+''.join(str(digit) for digit in ans[::-1])
    return ''.join(str(digit) for digit in ans[::-1])


def addition(n1, b1, n2, b2, b):
    n1_10 = convert_to_base_10(n1,b1)
    n2_10 = convert_to_base_10(n1,b1)
    ans = n1_10 + n2_10
    ans = convert_from_base_10(ans, b)
    return ans

def subtraction(n1, b1, n2, b2, b):
    n1_10 = convert_to_base_10(n1,b1)
    n2_10 = convert_to_base_10(n1,b1)
    ans = n1_10 - n2_10
    ans = convert_from_base_10(ans, b)
    return ans

def multiplication(n1, b1, n2, b2, b):
    n1_10 = convert_to_base_10(n1,b1)
    n2_10 = convert_to_base_10(n1,b1)
    ans = n1_10 * n2_10
    ans = convert_from_base_10(ans, b)
    return ans

print subtraction('1010', 2,'100', 10, 9)
print addition('1010', 2,'100', 10, 9)
print multiplication('1010', 2,'100', 10, 9)
\$\endgroup\$
  • \$\begingroup\$ Is that a homework task or such? For real production code I won't mix up base conversion with the math operation functions at all, since I don't see much additional value providing those functions. \$\endgroup\$ – πάντα ῥεῖ Apr 17 '17 at 18:21
  • 1
    \$\begingroup\$ If you convert everything to base 10 that way, you need to support all possible bases explicitly. For example, what if someone wants base 2047 ? I think the purpose of the homework was to have you write a general purpose module/class. \$\endgroup\$ – ChatterOne Apr 17 '17 at 22:23
1
\$\begingroup\$

For the conversion to base ten, you can just use the normal int function. It takes as a second argument a base (as int). In this case the first argument is required to be a string (so it has exactly the same interface as your convert_to_base_10 function.

For the convert_from_base_10 function, I would do something closer to this answer. It is recursive, which should be fine here (unless you convert numbers with more than a thousand digits in binary, because one thousand is the default maximum recursion depth in Python). It is also a lot easier to read, IMO.

Finally, your calculation functions all proceed after the same scheme:

  1. Convert the inputs to decimal
  2. Calculate the result in decimal
  3. Convert to the desired base

For this you could define a decorator that can wrap the actual calculation, which can then just assume everything is in base ten. So I would do:

def digit_to_char(digit):
    if digit < 10:
        return str(digit)
    return chr(ord('a') + digit - 10)


def str_base(number,base):
    if number < 0:
        return '-' + str_base(-number, base)
    d, m = divmod(number, base)
    if d > 0:
        return str_base(d, base) + digit_to_char(m)
    return digit_to_char(m)


def calculate_in_decimal(func):
    def wrapper(n1, b1, n2, b2, b):
        n1_10 = int(n1, b1)
        n2_10 = int(n2, b2)
        ans = func(n1_10, n2_10)
        return str_base(ans, b)


# Use it like this:
@calculate_in_decimal
def addition(n1, n2):
    return n1 + n2


# Or use the operator module:
import operator
multiplication = calculate_in_decimal(operator.mul)
subtraction = calculate_in_decimal(operator.sub)

Note that I also fixed a bug, you wrote:

n1_10 = convert_to_base_10(n1,b1)
n2_10 = convert_to_base_10(n1,b1)

Where it should be:

n1_10 = convert_to_base_10(n1,b1)
n2_10 = convert_to_base_10(n2,b2)
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.