Files

98 lines
2.5 KiB
Python

"""
COMP-3 Packed Decimal Verification for COBOL Migration Platform.
Validates that binary COMP-3 fields in RATE.dat are correctly encoded.
Usage: python verify_comp3.py
COMP-3 format: each byte holds 2 nibbles (4-bit digits),
last nibble = sign (0xC/0xF = positive, 0xD = negative).
PIC 9(1)V9(4) = 5 digits + sign = 3 bytes.
"""
import struct
import sys
def unpack_comp3(data: bytes) -> tuple[int, int, str]:
"""Unpack COMP-3 bytes -> (integer_value, decimal_places, sign)."""
nibbles = []
for byte in data:
nibbles.append((byte >> 4) & 0x0F)
nibbles.append(byte & 0x0F)
sign_nibble = nibbles[-1]
digit_nibbles = nibbles[:-1]
value = 0
for n in digit_nibbles:
value = value * 10 + n
if sign_nibble in (0xC, 0xF):
sign = "positive"
elif sign_nibble == 0xD:
sign = "negative"
else:
sign = f"unknown(0x{sign_nibble:X})"
return value, sign, data.hex()
def main():
rate_path = "D:/jcl-cobol/data/input/rate.dat"
with open(rate_path, "rb") as f:
data = f.read()
rec_size = 12 # PIC X(1) + PIC 9(1)V9(4) COMP-3(3) + PIC 9(8)
num_records = len(data) // rec_size
print(f"File: {rate_path}")
print(f"Size: {len(data)} bytes")
print(f"Records: {num_records}")
print()
expected = {
"C": ("Cash rate", 0.0005),
"O": ("Overdue rate", 0.0500),
}
all_ok = True
for i in range(num_records):
offset = i * rec_size
rec = data[offset : offset + rec_size]
rate_type = chr(rec[0])
pct_bytes = rec[1:4]
eff_date = rec[4:12].decode("ascii")
value, sign, pct_hex = unpack_comp3(pct_bytes)
int_part = value // 10000
dec_part = value % 10000
pct_float = int_part + dec_part / 10000
name, expected_val = expected.get(rate_type, ("Unknown", None))
match = abs(pct_float - expected_val) < 0.0001 if expected_val else False
status = "PASS" if match else "FAIL"
if not match:
all_ok = False
print(f"[{status}] Record {i+1}: type={rate_type} ({name})")
print(f" COMP-3 hex: {pct_hex}")
print(f" packed int: {value}")
print(f" float val: {pct_float:.4f}")
print(f" expected: {expected_val}")
print(f" eff date: {eff_date}")
print()
if all_ok:
print("=== ALL COMP-3 VALUES VERIFIED ===")
else:
print("=== COMP-3 MISMATCH DETECTED ===")
sys.exit(1)
if __name__ == "__main__":
main()