-
-
Save Francesco149/e94ac627c68999ddeec7139932b3f223 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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