Skip to content

Instantly share code, notes, and snippets.

@josiahcarlson
Last active January 3, 2016 11:59
Show Gist options
  • Save josiahcarlson/8459874 to your computer and use it in GitHub Desktop.
Save josiahcarlson/8459874 to your computer and use it in GitHub Desktop.
Pack large integers into doubles, and extract large integers from doubles.
'''
Written October 26, 2012 by Josiah Carlson
Released into the public domain.
I'm sure this has been done before, but I've not seen any code for it.
This code will take an integer with absolute value of up to 2**63-2**53
and pack it losslessly into an IEEE 753 FP double, preserving sort order
by reusing the exponent field for high order bits.
Note that if you keep your values under 2**62, we only use standard fp
values (no denormals).
This was originally written to allow for sorting of integers > 2**52
using Redis ZSETs without worrying about precision.
'''
import struct
_SHIFT = 2**52
def bigint_to_float(v, safe=True):
unsafe = not safe
assert isinstance(v, (int, long))
sign = -1 if v < 0 else 1
v *= sign
if safe:
assert v < 2**62
else:
# 2**63 - 2**53
assert v < 0x7fe0000000000000
exponent, mantissa = divmod(v, _SHIFT)
return sign * (_SHIFT + mantissa) * 2.0**(exponent-52-unsafe*1022)
def float_to_bigint(v, safe=True):
sign = -1 if v < 0 else 1
v *= sign
safe = bool(safe)
data = struct.pack('>d', v).encode('hex')
exponent = int(data[:3], 16)
assert exponent < 2048
return sign * (((exponent-1-safe*1022)<<52) + int(data[3:], 16))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment