53 lines
1.5 KiB
Python
53 lines
1.5 KiB
Python
from decimal import Decimal, getcontext
|
|
|
|
def convert_quad_hex_to_float(hex_str):
|
|
# Set high enough precision
|
|
getcontext().prec = 100
|
|
|
|
# Remove 0x prefix if present
|
|
hex_str = hex_str.lower().lstrip('0x')
|
|
|
|
if len(hex_str) != 32:
|
|
raise ValueError("Hex string must be exactly 32 characters (128 bits).")
|
|
|
|
# Convert to integer, then to binary string
|
|
int_val = int(hex_str, 16)
|
|
bin_str = f"{int_val:0128b}"
|
|
|
|
# Extract parts
|
|
sign_bit = int(bin_str[0], 2)
|
|
exponent_bits = bin_str[1:16]
|
|
fraction_bits = bin_str[16:]
|
|
|
|
# Interpret fields
|
|
sign = (-1) ** sign_bit
|
|
exponent = int(exponent_bits, 2)
|
|
bias = 16383 # Bias for quadruple precision
|
|
|
|
# Special cases
|
|
if exponent == 0 and int(fraction_bits, 2) == 0:
|
|
return Decimal(sign * 0)
|
|
elif exponent == 0x7FFF:
|
|
if int(fraction_bits, 2) == 0:
|
|
return Decimal('Infinity') if sign > 0 else Decimal('-Infinity')
|
|
else:
|
|
return Decimal('NaN')
|
|
|
|
# Compute fraction
|
|
fraction = Decimal(0)
|
|
for i, bit in enumerate(fraction_bits):
|
|
if bit == '1':
|
|
fraction += Decimal(1) / (Decimal(2) ** (i + 1))
|
|
|
|
# Add implicit 1 if normalized
|
|
if exponent != 0:
|
|
fraction = Decimal(1) + fraction
|
|
exponent_val = exponent - bias
|
|
else:
|
|
# Subnormal
|
|
exponent_val = 1 - bias
|
|
|
|
# Compute final value
|
|
value = Decimal(sign) * fraction * (Decimal(2) ** exponent_val)
|
|
return value
|
|
print(convert_quad_hex_to_float("0x4000921fb54442d18469898cc51701b8")) |