Skip to content

Instantly share code, notes, and snippets.

@Francesco149
Created November 19, 2018 00:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Francesco149/e94ac627c68999ddeec7139932b3f223 to your computer and use it in GitHub Desktop.
Save Francesco149/e94ac627c68999ddeec7139932b3f223 to your computer and use it in GitHub Desktop.
#!/usr/bin/env python
'''
utils to pack and unpack single-precision floats in IEEE 754
I wrote this to get used to bit twiddling with IEEE
this is free and unencumbered software released into the public domain
'''
import sys
import struct
import collections
def tof(x):
''' reinterpret integer as float '''
b = struct.pack('I', x)
return struct.unpack('f', b)[0]
def toi(f):
''' reinterpret float as integer '''
b = struct.pack('f', f)
return struct.unpack('I', b)[0]
def encode(sign, exp, mantissa):
''' encode sign, exp, mantissa as a float '''
sign = not not int(sign, 0)
exp = int(exp, 0) + 127
mantissa = int(mantissa, 0)
return tof(
((sign << 31) & 0x80000000) |
((exp << 23) & 0x7F800000) |
((mantissa << 0) & 0x007FFFFF)
)
FloatComponents = (
collections.namedtuple( "FloatComponents", ["sign", "exp", "mantissa"])
)
def decode(f):
''' decode a float into sign, exp, mantissa '''
x = toi(f)
sign = (x >> 31) & 1
exp = ((x >> 23) & 0xFF) - 127
mantissa = x & 0x007FFFFF
return FloatComponents(int(sign), int(exp), int(mantissa))
def convert(x):
''' detect type of x and use toi/tof accordingly '''
if isinstance(x, str):
if x.startswith("0x"):
x = int(x, 0)
else:
x = float(x)
if not isinstance(x, float):
f = tof(x)
return (f, decode(f))
return (toi(x), decode(x))
COMPFMT = " | sign=%d, exp=%d, mantissa=%08X"
def swap(x):
''' detect type of x, use toi/tof accordingly and format to string '''
y, components = convert(x)
if isinstance(y, int) or isinstance(y, long):
return str(x) + (" -> 0x%08X" % int(y)) + COMPFMT % components
return ("0x%08X -> " % int(x, 0)) + str(y) + COMPFMT % components
if __name__ == '__main__':
if len(sys.argv) == 2:
print(swap(sys.argv[1]))
elif len(sys.argv) == 4:
print(encode(*sys.argv[1:]))
else:
sys.stderr.write('''usage: %s number
converts between hex and single-precision float
number can be
- float: 123.123
- hex integer: 0xAABBCCDD
- sign exp mantissa: 0 2 0x00776655\n
''' % sys.argv[0])
sys.exit(1)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment