def compare_int_numbers(number1, number2):
    """
    Compares two numbers in the same base

    :param number1: a string representing a number
    :param number2: a string representing a number
    :return: -1 if the second number is bigger, 0 if they are equal, 1 if the first number is bigger
    """
    len1 = len(number1)
    len2 = len(number2)

    if len1 < len2:
        return -1
    elif len2 < len1:
        return 1
    else:
        for i in range(len1):
            if get_number_from_character(
                    number1[i]) < get_number_from_character(number2[i]):
                return -1
            elif get_number_from_character(
                    number1[i]) > get_number_from_character(number2[i]):
                return 1

        return 0
Beispiel #2
0
    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
Beispiel #3
0
    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 base_10_as_intermediate(number, source_base, destination_base):
        """
        It converts a number from base [source_base] in base [destination_base] using
        base 10 as intermediate base.

        :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")

        intermediate_in_base_10 = to_base_10(number, source_base)
        if destination_base > 10:
            result = Conversions.substitution_method(
                str(intermediate_in_base_10), 10, destination_base)
        else:
            result = Conversions.successive_divisions(
                str(intermediate_in_base_10), 10, destination_base)

        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
Beispiel #8
0
    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 to_base_10(number, base):
    """
    Utility function to convert a number to base 10

    :param number: a number in base [base]
    :param base: the base of the number [number]
    :return: integer representing the number in base 10
    """

    number_in_base_10 = 0

    exp = len(number) - 1
    for digit in number:
        number_in_base_10 += get_number_from_character(digit) * pow(base, exp)
        exp -= 1

    return number_in_base_10
Beispiel #10
0
    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