import struct
import math

def dynamic_bit_length(value):
    # Determine the minimum number of bits required for the mantissa
    mantissa, exponent = math.frexp(float(value))
    mantissa *= 2**53  # Assuming 53 bits of precision (double precision without the leading 1 bit)
    mantissa = int(mantissa)  # Convert to an integer to use bit_length
    exponent -= 53  # Adjust the exponent accordingly
    
    # Find out the minimum bits needed to represent the mantissa and exponent
    mantissa_bits = mantissa.bit_length()  # Now valid as mantissa is an integer
    exponent_bits = max(exponent.bit_length(), 1)  # At least 1 bit for exponent
    sign_bit = 1
    
    # We add 1 bit to store the length of the exponent in bits itself
    total_bits = sign_bit + 1 + exponent_bits + mantissa_bits
    return total_bits, mantissa, exponent

def d_float_encode(value):
    if value == 0:
        return (1, 0)  # using 1 bit to represent 0
    
    sign = 0 if value > 0 else 1
    value = abs(value)
    
    mantissa, exponent = math.frexp(value)
    # The mantissa is in the range [0.5, 1) for normalized numbers, we adjust to start with 1
    mantissa *= 2
    exponent -= 1  # Adjust the exponent to account for the mantissa scaling
    
    mantissa = int((mantissa - 1) * (252))  # Use 52 bits for the mantissa like in IEEE 754
    mantissa_bits = mantissa.bit_length()
    
    # We get the exponent’s bit-length, including an additional bit for storing the length itself
    exponent_bits_length = exponent.bit_length() + 1
    
    # The encoded value starts with the sign bit, followed by the exponent length, the exponent itself, and the mantissa
    d_float_value = (sign << (1 + exponent_bits_length + mantissa_bits)) | \
                    (exponent_bits_length << (exponent_bits_length + mantissa_bits - 1)) | \
                    (exponent << mantissa_bits) | \
                    mantissa
    
    total_bits = 1 + exponent_bits_length + mantissa_bits
    return (total_bits, d_float_value)

def d_float_decode(total_bits, encoded_value):
    # Early return for the simplest case, encoding for value 0
    if total_bits == 1:
        return 0.0
    
    # Extract sign bit
    sign = (encoded_value >> (total_bits - 1)) & 1
    
    # Decode the value, starting just after the sign bit
    value = encoded_value & ((1 << (total_bits - 1)) - 1)
    
    # Starting from left, read until the first ‘1’ bit is found
    # This marks the start of the exponent bits
    exponent_length = 0
    for i in range(total_bits - 2, -1, -1):  # Iterate from the bit before the sign bit to 0
        exponent_length += 1
        if (value >> i) & 1 == 1:  # Found the first ‘1’
            value &= ((1 << i) - 1)  # Clear all bits to the left, including the ‘1’ just found
            break
    
    # Next, retrieve the actual exponent
    exponent_start = i - exponent_length + 1
    exponent_bits = (value >> exponent_start) & ((1 << exponent_length) - 1)
    
    # Now, remove the exponent bits from the value to get the mantissa
    mantissa = value & ((1 << exponent_start) - 1)

    # Calculate the actual floating-point number
    exponent = exponent_bits - (1 << (exponent_length - 1))  # Remove bias from exponent
    mantissa /= (1 << (52 - exponent_length))  # Adjust mantissa to be a fraction again
    result = (1 + mantissa) * (2 ** exponent)  # Compute the floating-point number
    
    # Apply the sign
    if sign == 1:
        result = -result
    
    return result

for x in range(10) :
    num = float(input("Enter the number :"))  # Replace with the number you want to encode/decode
    total_bits, encoded = d_float_encode(num)
    decoded = d_float_decode(total_bits, encoded)

    print('Number to represent :',num)
    print(f"D-float Encoded: {encoded:0{total_bits}b} ({total_bits} bits)")
    print(f"D-float Decoded: {decoded}")