From cf8b73c3b346e2bf6fa842ec208e43a03f081d1e Mon Sep 17 00:00:00 2001 From: Tapash0110 Date: Mon, 30 Mar 2026 13:42:09 +0530 Subject: [PATCH] Implemented all hex operations under 5.8 by group 8. --- hex.py | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++++ test_hex.py | 41 +++++++++++++++++++++++++++ 2 files changed, 120 insertions(+) create mode 100644 hex.py create mode 100644 test_hex.py diff --git a/hex.py b/hex.py new file mode 100644 index 0000000..f3fd8e2 --- /dev/null +++ b/hex.py @@ -0,0 +1,79 @@ +class HexOperations: + def validate_hex(self, hex_str: str) -> str: + """Validates and extracts the hex part of the string.""" + if not hex_str.startswith("H'"): + raise ValueError("Invalid HEX format. Must start with H'") + hex_val = hex_str[2:] + if not hex_val: + raise ValueError("Empty HEX value") + try: + int(hex_val, 16) + except ValueError: + raise ValueError("Invalid HEX characters") + return hex_val + def validate_dec(self, dec_str: str) -> str: + """Validates and extracts the decimal part of the string.""" + if not dec_str.startswith("D'"): + raise ValueError("Invalid Decimal format. Must start with D'") + dec_val = dec_str[2:] + if not dec_val: + raise ValueError("Empty Decimal value") + try: + int(dec_val) + except ValueError: + raise ValueError("Invalid Decimal characters") + return dec_val + def hex(self, dec_str: str) -> str: + """Hexadecimal <-> Decimal conversions e.g. hex(D'243) returns H'F3""" + val = self.validate_dec(dec_str) + num = int(val) + return f"H'{hex(num)[2:].upper()}" + def dec(self, hex_str: str) -> str: + """Hexadecimal <-> Decimal conversions e.g. dec(H'1A5) is D'421""" + val = self.validate_hex(hex_str) + num = int(val, 16) + return f"D'{num}" + def add(self, hex1: str, hex2: str) -> str: + """Arithmetic operations in HEX base (Addition)""" + val1 = int(self.validate_hex(hex1), 16) + val2 = int(self.validate_hex(hex2), 16) + return f"H'{hex(val1 + val2)[2:].upper()}" + def subtract(self, hex1: str, hex2: str) -> str: + """Arithmetic operations in HEX base (Subtraction)""" + val1 = int(self.validate_hex(hex1), 16) + val2 = int(self.validate_hex(hex2), 16) + res = val1 - val2 + if res < 0: + return f"-H'{hex(abs(res))[2:].upper()}" + return f"H'{hex(res)[2:].upper()}" + def multiply(self, hex1: str, hex2: str) -> str: + """Arithmetic operations in HEX base (Multiplication)""" + val1 = int(self.validate_hex(hex1), 16) + val2 = int(self.validate_hex(hex2), 16) + return f"H'{hex(val1 * val2)[2:].upper()}" + def divide(self, hex1: str, hex2: str) -> str: + """Arithmetic operations in HEX base (Division)""" + val1 = int(self.validate_hex(hex1), 16) + val2 = int(self.validate_hex(hex2), 16) + if val2 == 0: + raise ValueError("Division by zero") + return f"H'{hex(val1 // val2)[2:].upper()}" + def complement_15s(self, hex_str: str) -> str: + """Complements (15's)""" + val = self.validate_hex(hex_str) + comp = "".join(hex(15 - int(c, 16))[2:].upper() for c in val) + return f"H'{comp}" + def complement_16s(self, hex_str: str) -> str: + """Complements (16's)""" + _15s = self.complement_15s(hex_str) + val = int(_15s[2:], 16) + 1 + # Pad with leading zeros based on original length, or standard hex length + # Standard approach: 15's complement + 1 + comp_16 = hex(val)[2:].upper() + # Ensure it maintains at least the length of the input (handle overflow if needed, but standard 16's comp just adds 1) + expected_len = len(hex_str) - 2 + comp_16 = comp_16.zfill(expected_len) + # If length exceeded (e.g., FFFF + 1 = 10000), we just take the last expected_len digits for proper 2s/16s comp behaviour + if len(comp_16) > expected_len: + comp_16 = comp_16[-expected_len:] + return f"H'{comp_16}" \ No newline at end of file diff --git a/test_hex.py b/test_hex.py new file mode 100644 index 0000000..6cb6f62 --- /dev/null +++ b/test_hex.py @@ -0,0 +1,41 @@ +import unittest +from hex import HexOperations +class TestHexOperations(unittest.TestCase): + def setUp(self): + self.hex_ops = HexOperations() + def test_hex_conversion(self): + # Hexadecimal <-> Decimal conversions e.g. "hex(D'243)" returns "H'F3", "dec(H'1A5)" is "D'421" + self.assertEqual(self.hex_ops.hex("D'243"), "H'F3") + def test_dec_conversion(self): + self.assertEqual(self.hex_ops.dec("H'1A5"), "D'421") + def test_add(self): + self.assertEqual(self.hex_ops.add("H'A", "H'5"), "H'F") + self.assertEqual(self.hex_ops.add("H'AB12", "H'1"), "H'AB13") + def test_subtract(self): + self.assertEqual(self.hex_ops.subtract("H'10", "H'A"), "H'6") + self.assertEqual(self.hex_ops.subtract("H'A", "H'10"), "-H'6") + def test_multiply(self): + self.assertEqual(self.hex_ops.multiply("H'2", "H'8"), "H'10") + def test_divide(self): + self.assertEqual(self.hex_ops.divide("H'10", "H'2"), "H'8") + def test_divide_by_zero(self): + with self.assertRaises(ValueError): + self.hex_ops.divide("H'10", "H'0") + def test_complement_15s(self): + self.assertEqual(self.hex_ops.complement_15s("H'A5"), "H'5A") + self.assertEqual(self.hex_ops.complement_15s("H'F3"), "H'0C") + def test_complement_16s(self): + self.assertEqual(self.hex_ops.complement_16s("H'A5"), "H'5B") + self.assertEqual(self.hex_ops.complement_16s("H'00"), "H'00") # 15s is FF -> +1 is 100 -> truncated to 00 + def test_invalid_input(self): + # Invalid prefix + with self.assertRaises(ValueError): + self.hex_ops.validate_hex("1A") + # Invalid chars + with self.assertRaises(ValueError): + self.hex_ops.validate_hex("H'1G") + # Decimal invalid + with self.assertRaises(ValueError): + self.hex_ops.validate_dec("D'ABC") +if __name__ == '__main__': + unittest.main() \ No newline at end of file