def compute_with_numbers(self, a: Number, b: Number) -> Number: if a.sign != b.sign: return Number(a.digits, a.sign) + (-b) elif a.sign == b.sign == Sign.negative: return (-b) - (-a) elif a < b: return Number((b - a).digits, Sign.negative) res = [] carry = 0 b_len = len(b) a_len = len(a) for i in range(max(a_len, b_len)): diff = (0 if i >= a_len else a[i]) - (0 if i >= b_len else b[i]) - carry if diff < 0: diff += CommandContext.Base carry = 1 else: carry = 0 res.append(diff) real_res_len = len(res) for digit in res[::-1]: if digit == 0: real_res_len -= 1 else: break if real_res_len <= 1: return Number([res[0]]) else: return Number(res[:real_res_len])
def test_negative_numbers_subtraction(token_stack): token_stack.push(Number([4, 5], Sign.negative)) token_stack.push(Number([2, 6], Sign.negative)) subtraction = Subtraction() result = subtraction.compute() assert result.sign == Sign.positive assert len(result.digits) == 1 assert result.digits[0] == 8
def test_leading_zero_removal(token_stack): token_stack.push(Number([3, 5])) token_stack.push(Number([1, 5])) subtraction = Subtraction() result = subtraction.compute() assert result.sign == Sign.positive assert len(result.digits) == 1 assert result.digits[0] == 2
def test_simple_carry(token_stack): token_stack.push(Number([3, 5])) token_stack.push(Number([5, 3])) subtraction = Subtraction() result = subtraction.compute() assert result.sign == Sign.positive assert len(result.digits) == 2 assert result.digits[0] == 8 assert result.digits[1] == 1
def test_opposite_signs_numbers_subtraction2(token_stack): token_stack.push(Number([2, 1], Sign.positive)) token_stack.push(Number([3, 1], Sign.negative)) subtraction = Subtraction() result = subtraction.compute() assert result.sign == Sign.positive assert len(result.digits) == 2 assert result.digits[0] == 5 assert result.digits[1] == 2
def compute_with_numbers(self, a: Number, b: Number) -> Number: if not b: raise DividingByZeroError() b_copy = Number(b.digits.copy()) q = Number([0]) r = Number(a.digits.copy()) while r >= b_copy: n = len(r) - len(b_copy) n_digits = [0 for _ in range(n)] n_digits.extend(b_copy.digits) n_number = Number(n_digits) if n_number > r: n -= 1 del n_number.digits[0] c = CommandContext.Base - 1 cal = n_number * Number([c]) while cal > r: c -= 1 cal = n_number * Number([c]) c_digits = [0 for _ in range(n)] c_digits.append(c) q = q + Number(c_digits) r = r - cal if a.sign != b.sign: q.sign = Sign.negative return q
def compute_with_numbers(self, a: Number, b: Number) -> Number: if a.sign != b.sign: if b.sign == Sign.negative: return a - (-b) else: return b - (-a) a_digits = a.digits.copy() b_digits = b.digits.copy() while len(a_digits) < len(b_digits): a_digits.append(0) while len(b_digits) < len(a_digits): b_digits.append(0) res_digits = [x + y for x, y in zip(a_digits, b_digits)] carry_over = 0 for i in range(len(res_digits)): res_digits[i] += carry_over carry_over = res_digits[i] // CommandContext.Base res_digits[i] = res_digits[i] % CommandContext.Base if carry_over != 0: res_digits.append(carry_over) else: while len(res_digits) > 1 and res_digits[-1] == 0: res_digits.pop() return Number(res_digits, a.sign)
def compute_with_numbers(self, a: Number, b: Number) -> Number: res = Number([0]) for offset, i in enumerate(a.digits): digits = [0 for _ in range(offset)] carry_over = 0 for index, j in enumerate(b.digits): compute = i * j + carry_over digits.append(compute % CommandContext.Base) carry_over = compute // CommandContext.Base if carry_over != 0: digits.append(carry_over) else: while len(digits) > 1 and digits[-1] == 0: digits.pop() res = res + Number(digits, Sign.positive) if a.sign != b.sign: res.sign = Sign.negative return res
def test_two_digits_subtraction(token_stack, ten): token_stack.push(Number([0, 5])) token_stack.push(ten) subtraction = Subtraction() result = subtraction.compute() assert result.sign == Sign.positive assert len(result.digits) == 2 assert result.digits[0] == 0 assert result.digits[1] == 4
def compute_with_numbers(self, a: Number, b: Number) -> Number: if not b: return Number([1]) if not b.sign: raise NegativePowerError() if b == Number([1]): return Number(a.digits, a.sign) elif not b[0] % 2: return self.compute_with_numbers(a * a, b / Number([2])) else: return a * self.compute_with_numbers( a * a, (b - Number([1])) / Number([2]))
def test_two_power_four(token_stack, two, four): token_stack.push(two) token_stack.push(four) power = Power() result = power.compute() assert result == Number([6, 1])
def test_one_power_two(token_stack, one, two): token_stack.push(one) token_stack.push(two) power = Power() result = power.compute() assert result == Number([1])
def large_number(): return Number([2, 6, 3, 8, 7, 6])
def minus_ninety_nine(): return Number([9, 9], Sign.negative)
def eight(): return Number([8])
def two(): return Number([2])
def minus_one(): return Number([1], Sign.negative)
def hundred(): return Number([0, 0, 1])
def zero_large(): return Number([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
def test_eight_power_four(token_stack, eight, four): token_stack.push(eight) token_stack.push(four) power = Power() result = power.compute() assert result == Number([6, 9, 0, 4])
def one(): return Number([1])
def test_ninety_nine_power_five(token_stack, ninety_nine, five): token_stack.push(ninety_nine) token_stack.push(five) power = Power() result = power.compute() assert result == Number([9, 9, 4, 0, 0, 9, 9, 0, 5, 9])
def four(): return Number([4])
def test_four_power_zero(token_stack, zero, four): token_stack.push(four) token_stack.push(zero) power = Power() result = power.compute() assert result == Number([1])
def ten(): return Number([0, 1])
def test_minus_one_power_four(token_stack, minus_one, four): token_stack.push(minus_one) token_stack.push(four) power = Power() result = power.compute() assert result == Number([1])
def nine_nine(): return Number([9, 9, 9, 9, 9, 9, 9, 9, 9])
def test_minus_one_power_five(token_stack, minus_one, five): token_stack.push(minus_one) token_stack.push(five) power = Power() result = power.compute() assert result == Number([1], Sign.negative)
def zero(): return Number([0])
def five(): return Number([5])