Exemple #1
0
    def from_str(val: str) -> DecimalNumber:
        values = val.split('.')
        if len(values) == 1 and len(values[0]) > 0:
            return DecimalNumber.from_integer(IntegerNumber.from_str(
                values[0]))
        elif len(values) == 2:
            if values[0][0] == '-':
                sign = Sign.NEGATIVE
                values[0] = values[0][1:]
            elif values[0][0] == '+':
                sign = Sign.POSITIVE
                values[0] = values[0][1:]
            elif values[0] == '0':
                sign = None
            else:
                sign = Sign.POSITIVE

            whole = FractionNumber(
                IntegerNumber.from_whole(WholeNumber.from_str(values[0])),
                IntegerNumber.from_str('1'))
            fractional = FractionNumber(
                IntegerNumber.from_whole(WholeNumber.from_str(values[1])),
                IntegerNumber.from_whole(
                    WholeNumber.from_str('1' + ('0' * len(values[1])))))

            final_frac = whole + fractional
            if sign == Sign.NEGATIVE:
                final_frac = final_frac * FractionNumber.from_str("-1/1")

            return DecimalNumber.from_fraction(final_frac)
        else:
            raise Exception(f'Bad format: {val}')
Exemple #2
0
    def __init__(self, numerator: IntegerNumber, denominator: IntegerNumber):
        if denominator == IntegerNumber.from_int(0):
            raise Exception('Denominator cannot be 0')

        self._numerator = numerator.copy()
        self._denominator = denominator.copy()
        self._normalize_sign()
Exemple #3
0
    def as_fraction(self: DecimalNumber) -> FractionNumber:
        log(f'Converting {self} to fraction number...')
        log_indent()

        log(f'Determining denominator based on length of fractional portion ({self.fractional})...'
            )
        denom = IntegerNumber.from_str('1' + '0' * len(self.fractional.digits))
        log(f'{denom}')

        log(f'Converting fractional portion ({self.fractional} to fraction...')
        fractional_fraction = FractionNumber(
            IntegerNumber.from_str(str(self.fractional)), denom)
        log(f'{fractional_fraction}')

        log(f'Converting whole portion ({self.whole}) to fraction...')
        whole_fraction = FractionNumber.from_whole(self.whole)
        log(f'{whole_fraction}')

        log(f'Adding ({whole_fraction}) to ({fractional_fraction})...')
        fraction = whole_fraction + fractional_fraction
        log(f'{fraction}')

        log(f'Applying sign of ({self.sign}) to {fraction}...')
        if self.sign == Sign.NEGATIVE:
            fraction = fraction * FractionNumber.from_str(
                "-1/1")  # make sign negative
        log(f'{fraction}')

        log_unindent()

        return fraction
Exemple #4
0
 def defineRandomIntegerNumber(self, numericalBase):
     l = randint(1, 10)
     representation = ""
     for i in range(l):
         representation += IntegerNumber.NumericalSymbols[randint(
             0, numericalBase - 1)]
     number = IntegerNumber(numericalBase, representation)
     number.removeLeadingZeros()
     return number
Exemple #5
0
def main():
    log_whitelist([(inspect.getfile(IntegerNumber), '__lt__')])

    print("<div style=\"border:1px solid black;\">", end="\n\n")
    print("`{bm-disable-all}`", end="\n\n")
    try:
        args = input().split()  # read from stdin
        input1 = IntegerNumber.from_str(args[0])
        input2 = IntegerNumber.from_str(args[1])
        res = input1 < input2  # this will output markdown to stdout
    finally:
        print("</div>", end="\n\n")
        print("`{bm-enable-all}`", end="\n\n")
Exemple #6
0
    def _normalize_sign(self: FractionNumber):
        # Normalize so that sign is on the numerator and the denominator is always positive
        if self._numerator.sign is None:  # sign of None means magnitude of 0
            pass  # if num's sign is None, the only value it can be is 0, so skip
        elif self._numerator.sign != self._denominator.sign:
            self._numerator = IntegerNumber(Sign.NEGATIVE,
                                            self._numerator.magnitude)
        elif self._numerator.sign == self._numerator.sign:
            self._numerator = IntegerNumber(Sign.POSITIVE,
                                            self._numerator.magnitude)

        self._denominator = IntegerNumber(Sign.POSITIVE,
                                          self._denominator.magnitude)
Exemple #7
0
    def will_division_terminate(lhs: DecimalNumber,
                                rhs: DecimalNumber) -> bool:
        log(f'Checking if {lhs} / {rhs} results in a non-terminating decimal...'
            )
        log_indent()

        adjust_len_self = len(lhs.fractional.digits)
        adjust_len_other = len(rhs.fractional.digits)

        log(f'Generating mock integer number for {lhs}...')
        lhs_extra_0s = adjust_len_self - len(lhs.fractional.digits)
        lhs_combined_digits = lhs.fractional.digits + lhs.whole.digits
        lhs_combined_digits[0:0] = [Digit(0)] * lhs_extra_0s
        mock_self = IntegerNumber(lhs.sign, WholeNumber(lhs_combined_digits))
        log(f'{mock_self}')

        log(f'Generating mock integer number for {rhs}...')
        rhs_extra_0s = adjust_len_other - len(rhs.fractional.digits)
        rhs_combined_digits = rhs.fractional.digits + rhs.whole.digits
        rhs_combined_digits[0:0] = [Digit(0)] * rhs_extra_0s
        mock_other = IntegerNumber(rhs.sign, WholeNumber(rhs_combined_digits))
        log(f'{mock_other}')

        log(f'Generating mock fraction for {lhs} / {rhs}...')
        mock_fraction = FractionNumber(mock_self, mock_other)
        log(f'{mock_fraction}')

        log(f'Simplifying mock fraction...')
        mock_fraction = mock_fraction.simplify()
        log(f'{mock_fraction}')

        log(f'Checking if prime factors of denom ({mock_fraction.denominator}) is {{}}, {{2}}, {{5}}, or {{2,5}}...'
            )
        mock_fraction_denom_prime_factors = set(
            factor_tree(mock_fraction.denominator).get_prime_factors())
        if not (
            {WholeNumber.from_str('2'),
             WholeNumber.from_str('5')} == mock_fraction_denom_prime_factors or
            {WholeNumber.from_str('2')} == mock_fraction_denom_prime_factors or
            {WholeNumber.from_str('5')} == mock_fraction_denom_prime_factors
                or 0 == len(mock_fraction_denom_prime_factors)):
            ret = False
            log(f'{ret} -- Won\'t terminate.')
        else:
            ret = True
            log(f'{ret} -- Will terminate.')

        log_unindent()
        log(f'{ret}')
        return ret
Exemple #8
0
    def common_denominator_lcm(
            lhs: FractionNumber,
            rhs: FractionNumber) -> (FractionNumber, FractionNumber):
        # Sign is only kept on the numerator, not the denominator
        log(f'Getting {lhs} and {rhs} to common denominator equivalent fractions'
            )
        if lhs._denominator != rhs._denominator:
            log_indent()

            log(f'Calculating common denominator...')
            common_denominator = lcm_prime_factorize(
                rhs._denominator.magnitude, lhs._denominator.magnitude)
            common_denominator = IntegerNumber(Sign.POSITIVE,
                                               common_denominator)
            log(f'{common_denominator}')

            log(f'Calculating numerator for LHS ({lhs})...')
            multiple, _ = common_denominator / lhs._denominator
            lhs_numerator = lhs._numerator * multiple
            log(f'{lhs_numerator}')

            log(f'Calculating numerator for RHS ({rhs})...')
            multiple, _ = common_denominator / rhs._denominator
            rhs_numerator = rhs._numerator * multiple
            log(f'{rhs_numerator}')

            log_unindent()

            lhs_equiv = FractionNumber(lhs_numerator, common_denominator)
            rhs_equiv = FractionNumber(rhs_numerator, common_denominator)
            log(f'Result: {lhs} -> {lhs_equiv}, {rhs} -> {rhs_equiv}')
            return lhs_equiv, rhs_equiv
        else:
            log(f'Fractions already have a common denominator')
            return lhs, rhs
Exemple #9
0
    def __mul__(lhs: DecimalNumber, rhs: DecimalNumber) -> DecimalNumber:
        log(f'Multiplying {lhs} and {rhs}...')
        log_indent()

        adjust_len_self = len(lhs.fractional.digits)
        adjust_len_other = len(rhs.fractional.digits)

        log(f'Generating mock integer number for {lhs}...')
        lhs_extra_0s = adjust_len_self - len(lhs.fractional.digits)
        lhs_combined_digits = lhs.fractional.digits + lhs.whole.digits
        lhs_combined_digits[0:0] = [Digit(0)] * lhs_extra_0s
        mock_self = IntegerNumber(lhs.sign, WholeNumber(lhs_combined_digits))
        log(f'{mock_self}')

        log(f'Generating mock integer number for {rhs}...')
        rhs_extra_0s = adjust_len_other - len(rhs.fractional.digits)
        rhs_combined_digits = rhs.fractional.digits + rhs.whole.digits
        rhs_combined_digits[0:0] = [Digit(0)] * rhs_extra_0s
        mock_other = IntegerNumber(rhs.sign, WholeNumber(rhs_combined_digits))
        log(f'{mock_other}')

        log(f'Performing {mock_self} * {mock_other}...')
        mock_ret = mock_self * mock_other
        log(f'{mock_ret}')

        log(f'Unmocking {mock_ret} back to decimal...')
        unadjust_len = adjust_len_self + adjust_len_other
        ret_sign = mock_ret.sign
        ret_fractional_digits = [
            mock_ret.magnitude[i] for i in range(0, unadjust_len)
        ]
        ret_whole_digits = [
            mock_ret.magnitude[i]
            for i in range(unadjust_len, len(mock_ret.magnitude.digits))
        ]
        ret = DecimalNumber(ret_sign, WholeNumber(ret_whole_digits),
                            FractionalNumber(ret_fractional_digits))
        log(f'{ret}')

        log_unindent()
        log(f'{ret}')

        return ret
Exemple #10
0
    def simplify(self: FractionNumber) -> FractionNumber:
        # Sign is on the numerator
        log(f'Simplifying {self}...')
        log_indent()

        log(f'Calculating GCD for ({self._numerator.magnitude}) and ({self._denominator.magnitude})...'
            )
        gcd = gcd_euclid(self._numerator.magnitude,
                         self._denominator.magnitude)
        log(f'GCD is {gcd}')

        log(f'Dividing numerator ({self._numerator.magnitude}) by {gcd}...')
        new_num, _ = self._numerator.magnitude / gcd
        log(f'New numerator is {new_num}...')

        log(f'Dividing denominator ({self._denominator.magnitude}) by {gcd}...'
            )
        new_den, _ = self._denominator.magnitude / gcd
        log(f'New numerator is {new_den}...')

        # Sign of fraction is on the numerator
        if self.sign == Sign.NEGATIVE:  # if original was negative, so will the simplified
            res = FractionNumber(IntegerNumber(Sign.NEGATIVE, new_num),
                                 IntegerNumber(Sign.POSITIVE, new_den))
        elif self.sign == Sign.POSITIVE:  # if original was positive, so will the simplified
            res = FractionNumber(IntegerNumber(Sign.POSITIVE, new_num),
                                 IntegerNumber(Sign.POSITIVE, new_den))
        else:  # if original was 0 (no sign), so will the simplified
            res = FractionNumber(IntegerNumber(None, new_num),
                                 IntegerNumber(Sign.POSITIVE, new_den))

        log_unindent()
        log(f'{self} simplified to: {res}')

        return res
Exemple #11
0
    def run(self):

        while True:
            try:
                self.displayMenu()
                command = input("Enter option: ")
                if command == "1":
                    n, m = self.readOperands()
                    print("\nResult: ", n, " + ", m, " = ", n + m, "\n")
                elif command == "2":
                    n, m = self.readOperands()
                    print("\nResult: ", n, " - ", m, " = ", n - m, "\n")
                elif command == "3":
                    n, m = self.readOperands()
                    print("\nResult: ", n, " * ", m, " = ", n * m, "\n")
                elif command == "4":
                    n = self.readIntegerNumber()
                    m = self.getSmallIntegerNumber()
                    print("\n Result: ")
                    print(
                        n, " / ", m, " = ", n // m, " remainder ",
                        IntegerNumber(n.getNumericalBase(),
                                      IntegerNumber.NumericalSymbols[n % m]))
                elif command == "5":
                    n = self.readIntegerNumber()
                    m = int(input("Enter destination base: "))
                    print("\nResult: ", n, " = ", n.conversionToBase(m))
                elif command == "x":
                    break
                else:
                    print("\nUnknown command...\n")
            except ValueError:
                print("\nValue should be an integer number.\n")
            except IntegerNumberException as ine:
                print("\n\n" + str(ine) + "\n\n")
            except Exception as e:
                print("\n\n" + str(e) + "\n\n")
            self.continuity()
Exemple #12
0
 def readIntegerNumber(self):
     """read a number"""
     numericalBase = int(input("Enter base: "))
     repr = input("Enter the number: ")
     return IntegerNumber(numericalBase, repr)
Exemple #13
0
    def to_suitable_fraction(value: FractionNumber) -> FractionNumber:
        log(f'Converting {value} to an equivalent fraction with denominator that is power of 10...'
            )
        log_indent()

        denom = value.denominator

        if str(denom)[0] == '1' and (set(str(denom)[1:]) == set()
                                     or set(str(denom)[1:]) == set('0')):
            log(f'Already power of 10')
        else:
            log(f'No')
            log(f'Simplifying fraction {value}...')
            value = value.simplify()
            denom = value.denominator
            log(f'{value}')

            log(f'Calculating unique prime factors of {denom}...')
            denom_prime_factors = factor_tree(denom).get_prime_factors()
            denom_prime_factors_set = set(denom_prime_factors)
            log(f'{denom_prime_factors_set}')
            if not ({WholeNumber.from_int(2),
                     WholeNumber.from_int(5)} == denom_prime_factors_set
                    or {WholeNumber.from_int(2)} == denom_prime_factors_set
                    or {WholeNumber.from_int(5)} == denom_prime_factors_set
                    or 0 == len(denom_prime_factors_set)):
                raise Exception(
                    'Simplified denominator contains prime factors other than 2 and 5'
                )

            log(f'Calculating value to scale by so {denom} becomes next largest power of 10...'
                )
            num_of_2s = len(
                list(
                    filter(lambda pf: pf == WholeNumber.from_str('2'),
                           denom_prime_factors)))
            num_of_5s = len(
                list(
                    filter(lambda pf: pf == WholeNumber.from_str('5'),
                           denom_prime_factors)))
            extra_2s = 0
            extra_5s = 0
            if num_of_2s == 0 and num_of_5s == 0:
                extra_2s = 1
                extra_5s = 1
            elif num_of_2s < num_of_5s:
                extra_2s = num_of_5s - num_of_2s
            elif num_of_2s > num_of_5s:
                extra_5s = num_of_2s - num_of_5s
            log(f'Require {extra_2s} 2s and {extra_5s} 5s')

            log(f'Multiplying {extra_2s} 2s and {extra_5s} 5s to get scale...')
            scale_by = WholeNumber.from_str('1')
            for i in range(extra_2s):
                scale_by *= WholeNumber.from_str('2')
            for i in range(extra_5s):
                scale_by *= WholeNumber.from_str('5')
            log(f'{scale_by}')

            log(f'Multiplying {value}\'s numerator and denominator by {scale_by}...'
                )
            value = value * FractionNumber(IntegerNumber.from_whole(scale_by),
                                           IntegerNumber.from_whole(scale_by))
            log(f'{value}')

        log_unindent()
        log(f'{value}')

        return value
Exemple #14
0
 def denominator(self: FractionNumber, denominator: WholeNumber):
     self._denominator = IntegerNumber(Sign.POSITIVE, denominator)
     self._normalize_sign()
Exemple #15
0
 def numerator(self: FractionNumber, numerator: WholeNumber):
     self._numerator = IntegerNumber(self._sign, numerator)
     self._normalize_sign()
Exemple #16
0
 def sign(self: FractionNumber, sign: Union[Sign, None]):
     self._numerator = IntegerNumber(sign, self._numerator.magnitude)
     self._normalize_sign()
Exemple #17
0
    def testConversions(self):
        assert (IntegerNumber(4,
                              "33221100").conversionToBase(9) == IntegerNumber(
                                  9, "106810"))
        assert (IntegerNumber(
            4, "123032122").conversionToBase(16) == IntegerNumber(16, "1B39A"))
        assert (IntegerNumber(4, "33221100") +
                IntegerNumber(4, "123032122") == IntegerNumber(4, "222313222"))
        assert (IntegerNumber(7,
                              "1230056").conversionToBase(4) == IntegerNumber(
                                  4, "212230223"))
        assert (IntegerNumber(7,
                              "445566").conversionToBase(4) == IntegerNumber(
                                  4, "103033320"))
        assert (IntegerNumber(16,
                              "ABCDE1").conversionToBase(4) == IntegerNumber(
                                  4, "222330313201"))
        assert (IntegerNumber(16, "7").conversionToBase(8) == IntegerNumber(
            8, "7"))
        assert (IntegerNumber(6, "54321").conversionToBase(5) == IntegerNumber(
            5, "214330"))
        assert (IntegerNumber(6, "3").conversionToBase(2) == IntegerNumber(
            2, "11"))

        assert (IntegerNumber(7, "1230056") -
                IntegerNumber(7, "445566") == IntegerNumber(7, "451160"))
        assert (IntegerNumber(16, "ABCDE1") *
                IntegerNumber(16, "7") == IntegerNumber(16, "4B2A127"))
        assert (IntegerNumber(6, "54321") // 3 == IntegerNumber(6, "15304"))
        assert (IntegerNumber(6, "54321") // 4 == IntegerNumber(6, "12350"))
        assert (IntegerNumber(10, "120") % 7 == 1)
        assert (IntegerNumber(10, "17") * IntegerNumber(10, "7") +
                IntegerNumber(10, "1") == IntegerNumber(10, "120"))
Exemple #18
0
 def from_str(val: str) -> FractionNumber:
     inputs = val.split('/', 2)
     return FractionNumber(IntegerNumber.from_str(inputs[0].strip()),
                           IntegerNumber.from_str(inputs[1].strip()))
Exemple #19
0
 def from_int(numerator: int) -> FractionNumber:
     return FractionNumber(IntegerNumber.from_int(numerator),
                           IntegerNumber.from_int(1))
Exemple #20
0
 def from_integer(numerator: IntegerNumber) -> FractionNumber:
     return FractionNumber(
         numerator, IntegerNumber.from_whole(WholeNumber.from_str('1')))