Srinivas Raju
Srinivas Raju

Reputation: 19

Conversion of mainframe S370 hexadecimal floating–point to decimal

I am reading a binary file from the mainframe and I would like to convert the single precession floating point numbers which are currently represented in HEX to be converted to its decimal equivalent in python. For example

X'42808000' ==> should be converted to 128.50 in decimal.. X'C2808000' ==> should be converted to -128.50 in decimal

Are they any built in functions in python that does this. It looks like the internal floating representations are not in IEEE format but the old "S370 mainframe hexadecimal format". Kindly let me know your thoughts on how to convert the same. Thanks

Upvotes: 1

Views: 313

Answers (1)

martineau
martineau

Reputation: 123473

It's unclear from your question where you say the numbers are currently represented in HEX, for the format of the S370 hexadecimal floating-point numbers, whether you meat that they're binary integer or string values, so I wrote a function that will accept either one.

try:
    basestring
except NameError:  # Python 3
    basestring = str

def hextofp(hexadecimal):
    """ Convert S370 hexadecimal floating-point number to Python
        binary floating point value (IEEE 754).
    """
    v = int(hexadecimal, 16) if isinstance(hexadecimal, basestring) else hexadecimal
    if v:  # not special case of "True 0"
        sign = -1 if v & 0x80000000 else 1
        exponent = ((v & 0x7f000000) >> 24) - 64  # remove bias
        fraction = float(v & 0x00ffffff) / 16777216  # divide by 2**24
        return sign * (fraction * 16**exponent)
    return 0.0

print('{:.2f}'.format(hextofp('42808000')))  # -> 128.50
print('{:.2f}'.format(hextofp(0x42808000)))  # -> 128.50
print('{:.2f}'.format(hextofp('C2808000')))  # -> -128.50
print('{:.3f}'.format(hextofp('40600000')))  # -> 0.375

# True 0
print('{:.1f}'.format(hextofp('00000000')))  # -> 0.0
# largest representable number
print('{:.8g}'.format(hextofp('7fffffff')))  # -> 7.2370051e+75
# smallest positive (normalized) number
print('{:.8g}'.format(hextofp('00100000')))  # -> 5.3976053e-79

# misc examples
print('{:.2f}'.format(hextofp('42500000')))  # -> 80.00
print('{:.2f}'.format(hextofp('41100000')))  # -> 1.00
print('{:.3f}'.format(hextofp('C276A000')))  # -> -118.625
print('{:.2f}'.format(hextofp('427b3333')))  # -> 123.20
print('{:.2f}'.format(hextofp('427b7333')))  # -> 123.45

Upvotes: 1

Related Questions