diff --git a/__pycache__/arithmetic.cpython-310.pyc b/__pycache__/arithmetic.cpython-310.pyc new file mode 100644 index 0000000..6400fc2 Binary files /dev/null and b/__pycache__/arithmetic.cpython-310.pyc differ diff --git a/__pycache__/binary.cpython-310.pyc b/__pycache__/binary.cpython-310.pyc new file mode 100644 index 0000000..32f9e7e Binary files /dev/null and b/__pycache__/binary.cpython-310.pyc differ diff --git a/__pycache__/bitwise.cpython-310.pyc b/__pycache__/bitwise.cpython-310.pyc new file mode 100644 index 0000000..e603c85 Binary files /dev/null and b/__pycache__/bitwise.cpython-310.pyc differ diff --git a/__pycache__/calculator.cpython-310.pyc b/__pycache__/calculator.cpython-310.pyc new file mode 100644 index 0000000..b36d094 Binary files /dev/null and b/__pycache__/calculator.cpython-310.pyc differ diff --git a/__pycache__/complex.cpython-310.pyc b/__pycache__/complex.cpython-310.pyc new file mode 100644 index 0000000..0fb981c Binary files /dev/null and b/__pycache__/complex.cpython-310.pyc differ diff --git a/__pycache__/exceptions.cpython-310.pyc b/__pycache__/exceptions.cpython-310.pyc new file mode 100644 index 0000000..723bb70 Binary files /dev/null and b/__pycache__/exceptions.cpython-310.pyc differ diff --git a/__pycache__/fraction.cpython-310.pyc b/__pycache__/fraction.cpython-310.pyc new file mode 100644 index 0000000..df51b2e Binary files /dev/null and b/__pycache__/fraction.cpython-310.pyc differ diff --git a/__pycache__/hex.cpython-310.pyc b/__pycache__/hex.cpython-310.pyc new file mode 100644 index 0000000..76f453e Binary files /dev/null and b/__pycache__/hex.cpython-310.pyc differ diff --git a/__pycache__/matrix.cpython-310.pyc b/__pycache__/matrix.cpython-310.pyc new file mode 100644 index 0000000..934acfe Binary files /dev/null and b/__pycache__/matrix.cpython-310.pyc differ diff --git a/__pycache__/octal.cpython-310.pyc b/__pycache__/octal.cpython-310.pyc new file mode 100644 index 0000000..3127d90 Binary files /dev/null and b/__pycache__/octal.cpython-310.pyc differ diff --git a/__pycache__/set.cpython-310.pyc b/__pycache__/set.cpython-310.pyc new file mode 100644 index 0000000..a070144 Binary files /dev/null and b/__pycache__/set.cpython-310.pyc differ diff --git a/__pycache__/test_arithmetic.cpython-310.pyc b/__pycache__/test_arithmetic.cpython-310.pyc new file mode 100644 index 0000000..ad7d3cb Binary files /dev/null and b/__pycache__/test_arithmetic.cpython-310.pyc differ diff --git a/__pycache__/test_binary.cpython-310.pyc b/__pycache__/test_binary.cpython-310.pyc new file mode 100644 index 0000000..3f233a8 Binary files /dev/null and b/__pycache__/test_binary.cpython-310.pyc differ diff --git a/__pycache__/test_bitwise.cpython-310.pyc b/__pycache__/test_bitwise.cpython-310.pyc new file mode 100644 index 0000000..65f0c15 Binary files /dev/null and b/__pycache__/test_bitwise.cpython-310.pyc differ diff --git a/__pycache__/test_calculator.cpython-310.pyc b/__pycache__/test_calculator.cpython-310.pyc new file mode 100644 index 0000000..2c9b5b1 Binary files /dev/null and b/__pycache__/test_calculator.cpython-310.pyc differ diff --git a/__pycache__/test_complex.cpython-310.pyc b/__pycache__/test_complex.cpython-310.pyc new file mode 100644 index 0000000..a921ae5 Binary files /dev/null and b/__pycache__/test_complex.cpython-310.pyc differ diff --git a/__pycache__/test_fraction.cpython-310.pyc b/__pycache__/test_fraction.cpython-310.pyc new file mode 100644 index 0000000..be371fb Binary files /dev/null and b/__pycache__/test_fraction.cpython-310.pyc differ diff --git a/__pycache__/test_hex.cpython-310.pyc b/__pycache__/test_hex.cpython-310.pyc new file mode 100644 index 0000000..0fb81d0 Binary files /dev/null and b/__pycache__/test_hex.cpython-310.pyc differ diff --git a/__pycache__/test_matrix.cpython-310.pyc b/__pycache__/test_matrix.cpython-310.pyc new file mode 100644 index 0000000..bb03403 Binary files /dev/null and b/__pycache__/test_matrix.cpython-310.pyc differ diff --git a/__pycache__/test_octal.cpython-310.pyc b/__pycache__/test_octal.cpython-310.pyc new file mode 100644 index 0000000..d51089f Binary files /dev/null and b/__pycache__/test_octal.cpython-310.pyc differ diff --git a/__pycache__/test_set.cpython-310.pyc b/__pycache__/test_set.cpython-310.pyc new file mode 100644 index 0000000..0113978 Binary files /dev/null and b/__pycache__/test_set.cpython-310.pyc differ diff --git a/__pycache__/test_trigonometric.cpython-310.pyc b/__pycache__/test_trigonometric.cpython-310.pyc new file mode 100644 index 0000000..7be3e2a Binary files /dev/null and b/__pycache__/test_trigonometric.cpython-310.pyc differ diff --git a/__pycache__/trigonometric.cpython-310.pyc b/__pycache__/trigonometric.cpython-310.pyc new file mode 100644 index 0000000..50571f0 Binary files /dev/null and b/__pycache__/trigonometric.cpython-310.pyc differ diff --git a/arithmetic.py b/arithmetic.py new file mode 100644 index 0000000..472d5d9 --- /dev/null +++ b/arithmetic.py @@ -0,0 +1,120 @@ +import math + + +def power(a, b): + x = float(a) + y = float(b) + res = x ** y + if res == int(res): + return str(int(res)) + return str(res) + + +def modulo(a, b): + x = float(a) + y = float(b) + if y == 0: + raise ValueError("modulo by zero") + res = x % y + if res == int(res): + return str(int(res)) + return str(res) + + +def floor_div(a, b): + x = float(a) + y = float(b) + if y == 0: + raise ValueError("floor division by zero") + res = x // y + return str(int(res)) + + +def sqrt(a): + x = float(a) + if x < 0: + raise ValueError("cant take sqrt of negative number") + res = math.sqrt(x) + if res == int(res): + return str(int(res)) + ".0" + return str(res) + + +def cbrt(a): + x = float(a) + if x >= 0: + res = x ** (1 / 3) + else: + res = -((-x) ** (1 / 3)) + res = round(res, 10) + if res == int(res): + return str(int(res)) + ".0" + return str(res) + + +def log(a): + x = float(a) + if x <= 0: + raise ValueError("log of non-positive number") + res = math.log10(x) + res = round(res, 10) + if res == int(res): + return str(int(res)) + ".0" + return str(res) + + +def ln(a): + x = float(a) + if x <= 0: + raise ValueError("ln of non-positive number") + res = math.log(x) + res = round(res, 10) + if res == int(res): + return str(int(res)) + ".0" + return str(res) + + +def exp(a): + x = float(a) + res = math.exp(x) + res = round(res, 10) + return str(res) + + +def ceil(a): + x = float(a) + return str(math.ceil(x)) + + +def floor(a): + x = float(a) + return str(math.floor(x)) + + +def factorial(n): + x = int(n) + if x < 0: + raise ValueError("factorial of negative number") + return str(math.factorial(x)) + + +def permutation(n, r): + n1 = int(n) + r1 = int(r) + if n1 < 0 or r1 < 0: + raise ValueError("need non-negative integers") + if n1 < r1: + raise ValueError("n must be >= r") + res = math.factorial(n1) // math.factorial(n1 - r1) + return str(res) + + +def combination(n, r): + n1 = int(n) + r1 = int(r) + if n1 < 0 or r1 < 0: + raise ValueError("need non-negative integers") + if n1 < r1: + raise ValueError("n must be >= r") + res = math.comb(n1, r1) + return str(res) diff --git a/binary.py b/binary.py new file mode 100644 index 0000000..eebd9cf --- /dev/null +++ b/binary.py @@ -0,0 +1,69 @@ +from exceptions import invalidbinaryerror + + +def check_binary(b): + b = b.strip() + if not b: + raise invalidbinaryerror("empty binary string") + for ch in b: + if ch not in ('0', '1'): + raise invalidbinaryerror(f"invalid digit: '{ch}'") + + +def binary_to_decimal(b): + b = b.strip() + check_binary(b) + return str(int(b, 2)) + + +def decimal_to_binary(d): + num = int(d.strip()) + if num < 0: + return '-' + bin(abs(num))[2:] + return bin(num)[2:] + + +def binary_add(a, b): + a, b = a.strip(), b.strip() + check_binary(a) + check_binary(b) + res = int(a, 2) + int(b, 2) + return bin(res)[2:] + + +def binary_subtract(a, b): + a, b = a.strip(), b.strip() + check_binary(a) + check_binary(b) + res = int(a, 2) - int(b, 2) + if res < 0: + return '-' + bin(abs(res))[2:] + return bin(res)[2:] + + +def binary_multiply(a, b): + a, b = a.strip(), b.strip() + check_binary(a) + check_binary(b) + res = int(a, 2) * int(b, 2) + return bin(res)[2:] + + +def ones_complement(b): + b = b.strip() + check_binary(b) + return ''.join('1' if bit == '0' else '0' for bit in b) + + +def twos_complement(b): + b = b.strip() + check_binary(b) + ones = ones_complement(b) + res = int(ones, 2) + 1 + width = len(b) + binary_res = bin(res)[2:] + if len(binary_res) > width: + binary_res = binary_res[-width:] + else: + binary_res = binary_res.zfill(width) + return binary_res diff --git a/exceptions.py b/exceptions.py new file mode 100644 index 0000000..3a45308 --- /dev/null +++ b/exceptions.py @@ -0,0 +1,48 @@ +class calculatorerror(Exception): + def __init__(self, msg="calculator error"): + self.msg = msg + super().__init__(self.msg) + +class invalidinputerror(calculatorerror): + def __init__(self, msg="invalid input"): + super().__init__(msg) + +class zerodenominatorerror(calculatorerror): + def __init__(self, msg="denominator cannot be zero"): + super().__init__(msg) + +class invalidfractionerror(calculatorerror): + def __init__(self, msg="invalid fraction format"): + super().__init__(msg) + +class invalidcomplexerror(calculatorerror): + def __init__(self, msg="invalid complex number"): + super().__init__(msg) + +class invalidbinaryerror(calculatorerror): + def __init__(self, msg="invalid binary number"): + super().__init__(msg) + +class invalidoctalerror(calculatorerror): + def __init__(self, msg="invalid octal number"): + super().__init__(msg) + +class invalidhexerror(calculatorerror): + def __init__(self, msg="invalid hex number"): + super().__init__(msg) + +class invalidseterror(calculatorerror): + def __init__(self, msg="invalid set format"): + super().__init__(msg) + +class invalidmatrixerror(calculatorerror): + def __init__(self, msg="invalid matrix format"): + super().__init__(msg) + +class dimensionmismatcherror(calculatorerror): + def __init__(self, msg="matrix dimensions dont match"): + super().__init__(msg) + +class undefinedoperationerror(calculatorerror): + def __init__(self, msg="operation is undefined"): + super().__init__(msg) diff --git a/test_arithmetic.py b/test_arithmetic.py new file mode 100644 index 0000000..d225600 --- /dev/null +++ b/test_arithmetic.py @@ -0,0 +1,143 @@ +import unittest +import arithmetic + + +class testarithmetic(unittest.TestCase): + + def test_power_positive(self): + self.assertEqual(arithmetic.power('2', '3'), '8') + + def test_power_zero_exponent(self): + self.assertEqual(arithmetic.power('5', '0'), '1') + + def test_power_one_exponent(self): + self.assertEqual(arithmetic.power('7', '1'), '7') + + def test_power_fractional(self): + self.assertEqual(arithmetic.power('4', '0.5'), '2') + + def test_power_negative_exponent(self): + self.assertEqual(arithmetic.power('2', '-1'), '0.5') + + def test_modulo(self): + self.assertEqual(arithmetic.modulo('10', '3'), '1') + + def test_modulo_no_remainder(self): + self.assertEqual(arithmetic.modulo('10', '5'), '0') + + def test_modulo_by_zero(self): + with self.assertRaises(ValueError): + arithmetic.modulo('5', '0') + + def test_floor_div(self): + self.assertEqual(arithmetic.floor_div('7', '2'), '3') + + def test_floor_div_exact(self): + self.assertEqual(arithmetic.floor_div('6', '3'), '2') + + def test_floor_div_by_zero(self): + with self.assertRaises(ValueError): + arithmetic.floor_div('5', '0') + + def test_sqrt(self): + self.assertEqual(arithmetic.sqrt('16'), '4.0') + + def test_sqrt_zero(self): + self.assertEqual(arithmetic.sqrt('0'), '0.0') + + def test_sqrt_non_perfect(self): + res = float(arithmetic.sqrt('2')) + self.assertAlmostEqual(res, 1.4142135623730951, places=5) + + def test_sqrt_negative(self): + with self.assertRaises(ValueError): + arithmetic.sqrt('-4') + + def test_cbrt(self): + self.assertEqual(arithmetic.cbrt('27'), '3.0') + + def test_cbrt_zero(self): + self.assertEqual(arithmetic.cbrt('0'), '0.0') + + def test_log(self): + self.assertEqual(arithmetic.log('100'), '2.0') + + def test_log_one(self): + self.assertEqual(arithmetic.log('1'), '0.0') + + def test_log_zero(self): + with self.assertRaises(ValueError): + arithmetic.log('0') + + def test_log_negative(self): + with self.assertRaises(ValueError): + arithmetic.log('-5') + + def test_ln_one(self): + self.assertEqual(arithmetic.ln('1'), '0.0') + + def test_ln_zero(self): + with self.assertRaises(ValueError): + arithmetic.ln('0') + + def test_exp_zero(self): + self.assertEqual(arithmetic.exp('0'), '1.0') + + def test_exp_one(self): + res = float(arithmetic.exp('1')) + self.assertAlmostEqual(res, 2.718281828, places=5) + + def test_ceil(self): + self.assertEqual(arithmetic.ceil('4.2'), '5') + + def test_ceil_integer(self): + self.assertEqual(arithmetic.ceil('4.0'), '4') + + def test_floor(self): + self.assertEqual(arithmetic.floor('4.8'), '4') + + def test_floor_integer(self): + self.assertEqual(arithmetic.floor('4.0'), '4') + + def test_factorial(self): + self.assertEqual(arithmetic.factorial('5'), '120') + + def test_factorial_zero(self): + self.assertEqual(arithmetic.factorial('0'), '1') + + def test_factorial_one(self): + self.assertEqual(arithmetic.factorial('1'), '1') + + def test_factorial_negative(self): + with self.assertRaises(ValueError): + arithmetic.factorial('-1') + + def test_permutation(self): + self.assertEqual(arithmetic.permutation('5', '2'), '20') + + def test_permutation_same(self): + self.assertEqual(arithmetic.permutation('5', '5'), '120') + + def test_permutation_zero_r(self): + self.assertEqual(arithmetic.permutation('5', '0'), '1') + + def test_permutation_invalid(self): + with self.assertRaises(ValueError): + arithmetic.permutation('2', '5') + + def test_combination(self): + self.assertEqual(arithmetic.combination('5', '2'), '10') + + def test_combination_same(self): + self.assertEqual(arithmetic.combination('5', '5'), '1') + + def test_combination_zero_r(self): + self.assertEqual(arithmetic.combination('5', '0'), '1') + + def test_combination_invalid(self): + with self.assertRaises(ValueError): + arithmetic.combination('2', '5') + + +if __name__ == "__main__": + unittest.main() diff --git a/test_binary.py b/test_binary.py new file mode 100644 index 0000000..0855007 --- /dev/null +++ b/test_binary.py @@ -0,0 +1,73 @@ +import unittest +from binary import ( + binary_to_decimal, decimal_to_binary, binary_add, + binary_subtract, binary_multiply, ones_complement, twos_complement +) +from exceptions import invalidbinaryerror + + +class testbinary(unittest.TestCase): + + def test_binary_to_decimal(self): + self.assertEqual(binary_to_decimal('1010'), '10') + + def test_binary_to_decimal_zero(self): + self.assertEqual(binary_to_decimal('0'), '0') + + def test_binary_to_decimal_one(self): + self.assertEqual(binary_to_decimal('1'), '1') + + def test_binary_to_decimal_large(self): + self.assertEqual(binary_to_decimal('11111111'), '255') + + def test_decimal_to_binary(self): + self.assertEqual(decimal_to_binary('10'), '1010') + + def test_decimal_to_binary_zero(self): + self.assertEqual(decimal_to_binary('0'), '0') + + def test_decimal_to_binary_one(self): + self.assertEqual(decimal_to_binary('1'), '1') + + def test_binary_add(self): + self.assertEqual(binary_add('011', '010'), '101') + + def test_binary_add_with_carry(self): + self.assertEqual(binary_add('111', '001'), '1000') + + def test_binary_subtract(self): + self.assertEqual(binary_subtract('110', '010'), '100') + + def test_binary_multiply(self): + self.assertEqual(binary_multiply('101', '11'), '1111') + + def test_ones_complement(self): + self.assertEqual(ones_complement('1010'), '0101') + + def test_ones_complement_all_zeros(self): + self.assertEqual(ones_complement('0000'), '1111') + + def test_ones_complement_all_ones(self): + self.assertEqual(ones_complement('1111'), '0000') + + def test_twos_complement(self): + self.assertEqual(twos_complement('1010'), '0110') + + def test_twos_complement_one(self): + self.assertEqual(twos_complement('0001'), '1111') + + def test_invalid_binary(self): + with self.assertRaises(invalidbinaryerror): + binary_to_decimal('1021') + + def test_invalid_binary_letters(self): + with self.assertRaises(invalidbinaryerror): + binary_to_decimal('10a1') + + def test_invalid_binary_empty(self): + with self.assertRaises(invalidbinaryerror): + binary_to_decimal('') + + +if __name__ == "__main__": + unittest.main()