def division_op(number1, number2, base): """ This function performs the division of two numbers ([number1] and [number2]) in base [base] :param number1: a string representing the first number in base [base] :param number2: a string representing the second number in base [base] having one digit :param base: the base in which the numbers are represented and the division is done :return: two strings representing the quotient and reminder of the division between [number1] and [number2] Raises a ValueError if [number2] if 0 or if is has more than one digit """ if number2 == '0': raise ValueError("Cannot divide by 0") if len(number2) != 1: raise ValueError("Invalid operand") if base == 10: return str(int(number1) // int(number2)), str( int(number1) % int(number2)) else: max_len = len(number1) result = "" num_to_div_str = "" # we do the division looping through the number for i in range(max_len): num_to_div_str += number1[i] if len(num_to_div_str) == 1: if get_number_from_character( number1[i]) < get_number_from_character( number2[0]): if i != 0: result += '0' continue num_to_div = to_base_10(num_to_div_str, base) div = get_number_from_character(number2[0]) last_digit = num_to_div // div result = result + get_character_from_number(last_digit) if num_to_div % div != 0: num_to_div_str = get_character_from_number(num_to_div % div) else: num_to_div_str = "" # if the reminder is "" then it is 0 if num_to_div_str == "": num_to_div_str = "0" # if the result is "" we return 0 if result == "": return '0', num_to_div_str else: return result, num_to_div_str
def addition(number1, number2, base): """ This function performs the addition of two numbers ([number1] and [number2]) in base [base] :param number1: a string representing the first number in base [base] :param number2: a string representing the second number in base [base] :param base: the base in which the numbers are represented and the addition is done :return: a string representing the sum of [number1] and [number2] """ if base == 10: # if the numbers are in base 10 we do return str( int(number1) + int(number2)) # the normal addition of two numbers in base 10 else: reminder = 0 if len(number1) < len( number2): # compare the length of the numbers aux = number1 # and put the longest in number1 number1 = number2 number2 = aux min_len = len(number2) max_len = len(number1) diff = max_len - min_len result = "" # go through the numbers from last digit to the first digit of the shortest and do the addition for i in range(min_len - 1, -1, -1): last_digit = (get_number_from_character(number1[i + diff]) + get_number_from_character(number2[i]) + reminder) % base result = result + get_character_from_number(last_digit) reminder = (get_number_from_character(number1[i + diff]) + get_number_from_character(number2[i]) + reminder) // base # if the numbers had the same length we put the reminder as the first digit if it is not 0 if max_len == min_len and reminder != 0: result = result + get_character_from_number(reminder) # if they had not the same length we add the digits of the longest and add the reminder to them elif max_len > min_len: for i in range(max_len - min_len - 1, -1, -1): last_digit = (get_number_from_character(number1[i]) + reminder) % base result = result + get_character_from_number(last_digit) reminder = (get_number_from_character(number1[i]) + reminder) // base # reverse the digits of the result to obtain the correct number result = result[::-1] return result
def multiplication(number1, number2, base): """ This function performs the multiplication of two numbers ([number1] and [number2]) in base [base] :param number1: a string representing the first number in base [base] :param number2: a string representing the second number in base [base] having one digit :param base: the base in which the numbers are represented and the multiplication is done :return: two strings representing product of [number1] and [number2] Raises a ValueError if [number2] is 0 or if is has more than one digit """ if base == 10: return str(int(number1) * int(number2)) else: # find the number having one digit if len(number1) == 1 and len(number2) > 1: to_mul = number1 to_be_mul_int = number2 else: to_mul = number2 to_be_mul_int = number1 reminder = 0 max_len = len(to_be_mul_int) result = "" if len(to_mul) != 1: raise ValueError("Invalid operand") else: for i in range(max_len - 1, -1, -1): last_digit = (get_number_from_character(to_be_mul_int[i]) * get_number_from_character(to_mul[0]) + reminder) % base result = result + get_character_from_number(last_digit) reminder = (get_number_from_character(to_be_mul_int[i]) * get_number_from_character(to_mul[0]) + reminder) // base # if the reminder is not 0 then we add it at the beginning of the result if reminder != 0: result += get_character_from_number(reminder) # reverse the digits to get the correct number result = result[::-1] if result[0] == '0': return '0' else: return result
def successive_divisions(number, source_base, destination_base): """ It converts a number from base [source_base] in base [destination_base] using the successive divisions algorithm. :param number: string representing number in base [source_base] :param source_base: the source base :param destination_base: the destination base :return: converted number Raises ValueError if the number contains digits >= than the source_base """ for x in number: if get_number_from_character(x) >= source_base: raise ValueError("Invalid number in source base") quotient = number result = "" destination_base = get_character_from_number(destination_base) while quotient != "0": quotient, reminder = Operations.division_op( quotient, destination_base, source_base) result += reminder result = result[::-1] return result
def substitution_method(number, source_base, destination_base): """ It converts a number from base [source_base] in base [destination_base] using the substitution algorithm. :param number: string representing number in base [source_base] :param source_base: the source base [2-16] :param destination_base: the destination base [2-16] :return: converted number Raises ValueError if the number contains digits >= than the source_base """ for x in number: if get_number_from_character(x) >= source_base: raise ValueError("Invalid number in source base") result = "0" exp = len(number) - 1 for digit in number: current_power = "1" for i in range(exp): current_power = Operations.multiplication( current_power, get_character_from_number(source_base), destination_base) current_power = Operations.multiplication(current_power, digit, destination_base) result = Operations.addition(result, current_power, destination_base) exp -= 1 return result
def rapid_conversions(number, source_base, destination_base): """ It converts a number from base [source_base] in base [destination_base] using the rapid conversions algorithm. :param number: string representing number in base [source_base] :param source_base: the source base [2, 4, 8, or 16] :param destination_base: the destination base [2, 4, 8, or 16] :return: converted number Raises ValueError if the bases are not [2, 4, 8 or 16] or if the number contains digits >= than the source_base """ allowed_bases = [2, 4, 8, 16] if source_base not in allowed_bases or destination_base not in allowed_bases: raise ValueError("Invalid source base for rapid conversions") for x in number: if get_number_from_character(x) >= source_base: raise ValueError("Invalid number in source base") pow_2_source = int(math.log2(source_base)) pow_2_destination = int(math.log2(destination_base)) bits = [] for i in range(len(number) - 1, -1, -1): digit = get_number_from_character(number[i]) for j in range(pow_2_source): bits.append(digit % 2) digit //= 2 while len(bits) % pow_2_destination != 0: bits.append(0) result = "" for i in range(0, len(bits), pow_2_destination): digit = get_character_from_number( sum([bits[i + j] * (1 << j) for j in range(pow_2_destination)])) result += digit result = result[::-1] return result
def subtraction(number1, number2, base): """ This function performs the subtraction of two numbers ([number1] and [number2]) in base [base] :param number1: a string representing the first number in base [base] :param number2: a string representing the second number in base [base] :param base: the base in which the numbers are represented and the subtraction is done :return: two strings representing difference between [number1] and [number2] Raises a ValueError if [number2] is greater than [number1] """ if base == 10: return str(int(number1) - int(number2)) else: if compare_int_numbers(number1, number2) == -1: raise ValueError("The subtrahend is greater than minuend") reminder = 0 if len(number1) < len(number2): raise ValueError("The subtrahend is greater than minuend") else: min_len = len(number2) max_len = len(number1) diff = max_len - min_len result = "" # go through the numbers from last digit to the first digit of the shortest and do the subtraction for i in range(min_len - 1, -1, -1): minuend = get_number_from_character(number1[i + diff]) sub = get_number_from_character(number2[i]) if minuend < sub + reminder: last_digit = minuend + base - sub - reminder reminder = 1 else: last_digit = minuend - sub - reminder reminder = 0 result = result + get_character_from_number(last_digit) if max_len == min_len and reminder != 0: result = result + get_character_from_number(reminder) # if the first number is longer than the second we put its digits athe the beginning # of the result subtracting the reminder elif max_len > min_len: for i in range(max_len - min_len - 1, -1, -1): if get_number_from_character(number1[i]) < reminder: last_digit = get_number_from_character( number1[i]) + base - reminder reminder = 1 else: last_digit = get_number_from_character( number1[i]) - reminder reminder = 0 result = result + get_character_from_number(last_digit) # reverse the digits to get the correct number result = result[::-1] if result != "0": result = result.lstrip("0") return result