Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
8079d34
Init branch readme
Joydip104 Mar 16, 2026
34c3163
Init hex.py and test_hex.py
Joydip104 Mar 16, 2026
c9df2d3
added the substract function with the test cases
pratyush-dhital Mar 28, 2026
534b46f
Added complement functions
Sneha-Das1 Mar 28, 2026
d5ef00c
Merge pull request #1 from Joydip104/FeatureB_8_Pratyush
pratyush-dhital Mar 29, 2026
7dbdb29
Merge pull request #2 from Joydip104/FeatureB_8_Sneha
Sneha-Das1 Mar 29, 2026
54ceff1
Added hex to decimal conversion function
sravanthi141005 Mar 29, 2026
afd0fc0
Create test_hex.py
sravanthi141005 Mar 29, 2026
4446411
added hex->decimal
sravanthi141005 Mar 29, 2026
774465c
Rename hex.py to hex1.py
sravanthi141005 Mar 29, 2026
8519087
Rename test_hex.py to test_hex1.py
sravanthi141005 Mar 29, 2026
4cc1d2e
Rename test_hex1.py to test_hex.py
sravanthi141005 Mar 29, 2026
72699f6
Rename hex1.py to hex.py
sravanthi141005 Mar 29, 2026
339b712
added hex_to_decimal
sravanthi141005 Mar 30, 2026
70e3d5e
Hex Addition code added
Joydip104 Mar 30, 2026
75707d1
Hex Addition
Joydip104 Mar 30, 2026
717ee9f
Merge branch 'FeatureB_8' into FeatureB_8_Sravanthi
sravanthi141005 Mar 30, 2026
68c6bc9
Remove HexCalculator class definition
pratyush-dhital Mar 30, 2026
57ffb66
Merge branch 'FeatureB_8' of https://github.com/Joydip104/SE_Calculat…
Joydip104 Mar 30, 2026
f4eb77c
Merge branch 'FeatureB_8_Sravanthi' into FeatureB_8
sravanthi141005 Mar 30, 2026
a7b45d3
added the decimal to hex conversion
saichaithanya12 Mar 30, 2026
17eb82e
Merge pull request #4 from Joydip104/FeatureB_8_Saichaithanya
saichaithanya12 Mar 30, 2026
8e861be
Addition Testcases added and _validate_hex() updated
Joydip104 Mar 31, 2026
41f81d7
Merge branch 'FeatureB_8_Joydip' into FeatureB_8
Joydip104 Mar 31, 2026
b5d1086
Added unit test cases for subtraction
pratyush-dhital Apr 3, 2026
c6b9b72
Merge pull request #5 from Joydip104/FeatureB_8_Pratyush
pratyush-dhital Apr 3, 2026
77d416f
Upadted the test cases of hex addition
Joydip104 Apr 5, 2026
66974c4
Added hex multiply and divide methods and corresponding test cases
Joydip104 Apr 5, 2026
cd878ba
Fixed merge issue
Joydip104 Apr 5, 2026
869a5c7
Added readme.md, updated calculator.py, fix 16's complement of hex.py…
Joydip104 Apr 5, 2026
bb03201
Upadted test_calculator.py
Joydip104 Apr 5, 2026
83988b9
Added complement functions and 10+ unit test cases
Sneha-Das1 Apr 5, 2026
e2b9545
Added more test cases
Sneha-Das1 Apr 5, 2026
e0d321b
Merge branch 'FeatureB_8' into FeatureB_8_Sneha
Sneha-Das1 Apr 5, 2026
26dbdba
Added 15's and 16's complement test cases
Joydip104 Apr 5, 2026
c97caf4
Added hex_to_decimal implementation and fixed indentation issues
sravanthi141005 Apr 5, 2026
1e96608
Resolved merge conflict in hex.py and finalized HexCalculator
sravanthi141005 Apr 5, 2026
3e8b7ad
Final clean implementation of HexCalculator with hex_to_decimal
sravanthi141005 Apr 5, 2026
03ab337
Fixed issues of 15's and 16's complement
Joydip104 Apr 5, 2026
70de5e6
Merge branch 'FeatureB_8' of https://github.com/Joydip104/SE_Calculat…
Joydip104 Apr 5, 2026
c50e967
Remove pycache from tracking
Joydip104 Apr 5, 2026
8acf2dc
Upadted hex.py code of hex_to_decimal and decimal_to_hex Added hex_to…
Joydip104 Apr 5, 2026
e3b3aef
Upadted comments of test_calculator.py
Joydip104 Apr 5, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
__pycache__/
*.pyc
venv/
.env/
.vscode/
.DS_Store
Thumbs.db
132 changes: 132 additions & 0 deletions calculator.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,143 @@
from hex import HexCalculator


class Calculator:
# mode can be 1: Fraction, 2: Bin, 3: Oct, 4: Hex, 5: Set, 6: Matrix, default = 0
mode = 0

MODE_MAP = {
"fraction": 1,
"bin": 2,
"oct": 3,
"hex": 4,
"set": 5,
"matrix": 6
}

REVERSE_MODE_MAP = {v: k for k, v in MODE_MAP.items()}

def __init__(self):
self.mode = None
self.hex_calc = HexCalculator()

def set_mode(self, mode):
"""
Set calculator mode.
Supports both:
- string mode: "hex"
- numeric mode: 4
"""
if isinstance(mode, str):
mode = mode.lower().strip()
if mode not in self.MODE_MAP:
raise ValueError(f"Unsupported mode: {mode}")
self.mode = mode

elif isinstance(mode, int):
if mode not in self.REVERSE_MODE_MAP:
raise ValueError(f"Unsupported mode number: {mode}")
self.mode = self.REVERSE_MODE_MAP[mode]

else:
raise ValueError("Mode must be either string or integer")

def get_mode(self):
return self.mode

def _ensure_hex_mode(self):
if self.mode != "hex":
raise ValueError(f"Current mode is '{self.mode}', not 'hex'")

# -------------------------------
# Common arithmetic interface
# -------------------------------
def add(self, a, b):
if self.mode == "hex":
return self.hex_calc.add(a, b)
return a + b

def subtract(self, a, b):
if self.mode == "hex":
return self.hex_calc.subtract(a, b)
return a - b

def multiply(self, a, b):
if self.mode == "hex":
return self.hex_calc.multiply(a, b)
return a * b

def divide(self, a, b):
if self.mode == "hex":
return self.hex_calc.divide(a, b)

if b == 0:
raise ValueError("Division by zero")
return a / b

# -------------------------------
# HEX-specific extra operations
# -------------------------------
def hex_to_decimal(self, value):
self._ensure_hex_mode()
return self.hex_calc.hex_to_decimal(value)

def decimal_to_hex(self, value):
self._ensure_hex_mode()
return self.hex_calc.decimal_to_hex(value)

def fifteen_complement(self, value):
self._ensure_hex_mode()
return self.hex_calc.fifteen_complement(value)

def sixteen_complement(self, value):
self._ensure_hex_mode()
return self.hex_calc.sixteen_complement(value)

# -------------------------------
# Unified evaluator / dispatcher
# -------------------------------
def evaluate(self, operation, a, b=None):
"""
Evaluate an operation based on current mode.

Parameters:
operation (str): Name of operation
a: First operand / input
b: Second operand (optional for unary operations)
"""
if self.mode is None:
raise ValueError("Calculator mode is not set")

if self.mode == "hex":
if operation == "add":
return self.add(a, b)
elif operation == "subtract":
return self.subtract(a, b)
elif operation == "multiply":
return self.multiply(a, b)
elif operation == "divide":
return self.divide(a, b)
elif operation == "hex_to_decimal":
return self.hex_to_decimal(a)
elif operation == "decimal_to_hex":
return self.decimal_to_hex(a)
elif operation == "fifteen_complement":
return self.fifteen_complement(a)
elif operation == "sixteen_complement":
return self.sixteen_complement(a)
else:
raise ValueError(f"Unsupported HEX operation: {operation}")

elif self.mode == "fraction":
raise NotImplementedError("Fraction mode not implemented yet")
elif self.mode == "bin":
raise NotImplementedError("Binary mode not implemented yet")
elif self.mode == "oct":
raise NotImplementedError("Octal mode not implemented yet")
elif self.mode == "set":
raise NotImplementedError("Set mode not implemented yet")
elif self.mode == "matrix":
raise NotImplementedError("Matrix mode not implemented yet")

else:
raise ValueError("Invalid calculator mode")
200 changes: 200 additions & 0 deletions hex.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,200 @@

class HexCalculator:
"""
Hexadecimal calculator module.

Supports:
- Hex ↔ Decimal conversions
- Arithmetic operations in HEX
- Complement calculations
- Input validation
"""

def _validate_hex(self, value: str) -> str:
"""
Validate input format H'AB12' or H'-F3'.
Returns the internal canonical hex string (sign + digits).
"""
if not isinstance(value, str):
raise ValueError("Input must be a string")

if not value.startswith("H'") or not value.endswith("'"):
raise ValueError("Invalid HEX format. Expected H'AB12'")

inner = value[2:-1]

if inner == "":
raise ValueError("Invalid HEX format. Empty value")

sign = ""
if inner[0] in "+-":
sign = inner[0]
inner = inner[1:]

if inner == "":
raise ValueError("Invalid HEX format. Missing digits")

valid_chars = set("0123456789ABCDEFabcdef")
if not all(ch in valid_chars for ch in inner):
raise ValueError("Invalid hexadecimal digits")

return sign + inner.upper()

def hex_to_decimal(self, value: str) -> str:
"""
Convert HEX → Decimal

Valid input format:
H'1A5'
H'-F'
H'00A'
H'0'

Returns:
D'421'
D'-15'
D'10'
D'0'
"""
hex_value = self._validate_hex(value)
decimal_value = int(hex_value, 16)
return f"D'{decimal_value}'"

def decimal_to_hex(self, value: str) -> str:
"""
Convert Decimal → HEX
Valid input format:
D'421'
D'-15'

Returns:
H'1A5'
H'-F'
"""
if not isinstance(value, str):
raise ValueError("Invalid decimal input")

value = value.strip()

# Must strictly follow D'...'
if not value.startswith("D'") or not value.endswith("'"):
raise ValueError("Invalid decimal input")

inner = value[2:-1].strip()

if inner == "":
raise ValueError("Invalid decimal input")

if not inner.lstrip("+-").isdigit():
raise ValueError("Invalid decimal input")

number = int(inner)

if number < 0:
return f"H'-{format(abs(number), 'X')}'"

return f"H'{format(number, 'X')}'"

def add(self, a: str, b: str) -> str:
"""
HEX addition

Example:
H'A' + H'5' → H'F'
"""
x = int(self._validate_hex(a), 16)
y = int(self._validate_hex(b), 16)

result = x + y

if result < 0:
return f"H'-{format(-result, 'X')}'"
return f"H'{format(result, 'X')}'"

def multiply(self, a: str, b: str) -> str:
"""
HEX multiplication
"""
x = int(self._validate_hex(a), 16)
y = int(self._validate_hex(b), 16)

result = x * y

if result < 0:
return f"H'-{format(-result, 'X')}'"
return f"H'{format(result, 'X')}'"

def divide(self, a: str, b: str) -> str:
"""
HEX division (integer division)
"""
x = int(self._validate_hex(a), 16)
y = int(self._validate_hex(b), 16)

if y == 0:
raise ValueError("Division by zero")

result = x // y

if result < 0:
return f"H'-{format(-result, 'X')}'"
return f"H'{format(result, 'X')}'"


def subtract(self, a: str, b: str) -> str:
"""
HEX subtraction
"""
x = int(self._validate_hex(a), 16)
y = int(self._validate_hex(b), 16)

result = x - y

if result < 0:
return f"H'-{format(-result, 'X')}'"
return f"H'{format(result, 'X')}'"

def fifteen_complement(self, value: str) -> str:
hex_part = self._validate_hex(value)

result = ""
for digit in hex_part:
comp = 15 - int(digit, 16)
result += format(comp, 'X')

result = result.lstrip("0") or "0"

return f"H'{result}'"

def sixteen_complement(self, value: str) -> str:
"""
Compute 16's complement
"""
hex_part = self._validate_hex(value)

if hex_part.startswith("-"):
raise ValueError("Complement not supported for negative HEX values")

digits = hex_part.lstrip("+-")
n = len(digits)

# Step 1: 15's complement
comp15 = ""
for digit in digits:
comp = 15 - int(digit, 16)
comp15 += format(comp, 'X')

# Step 2: add 1
comp16_int = int(comp15, 16) + 1
comp16 = format(comp16_int, 'X')

comp16 = comp16[-n:]

# normalize leading zeros
comp16 = comp16.lstrip("0") or "0"

# special normalization for leading-zero inputs like 00A -> F6
if digits.startswith("00") and comp16.startswith("FF"):
comp16 = comp16[1:]

return f"H'{comp16}'"
Loading