Exemplo n.º 1
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
Exemplo n.º 2
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}')
Exemplo n.º 3
0
def main():
    log_whitelist([(inspect.getfile(FractionNumber), '__add__')])

    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 = FractionNumber.from_str(args[0])
        input2 = FractionNumber.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")
Exemplo n.º 4
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
Exemplo n.º 5
0
 def from_int(value: int) -> DecimalNumber:
     return DecimalNumber.from_fraction(FractionNumber.from_int(value))
Exemplo n.º 6
0
 def from_integer(value: IntegerNumber) -> DecimalNumber:
     return DecimalNumber.from_fraction(FractionNumber.from_integer(value))
Exemplo n.º 7
0
 def from_whole(value: WholeNumber) -> DecimalNumber:
     return DecimalNumber.from_fraction(FractionNumber.from_whole(value))
Exemplo n.º 8
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