[Python-Dev] Adding DBL_MANTISSA and such to Python

Josiah Carlson jcarlson at uci.edu
Thu May 5 09:27:54 CEST 2005


"Edward C. Jones" <edcjones at comcast.net> wrote:

> 3. Add full "tostring" and "fromstring" capabilities for Python numeric 
> types. "tostring(x)" would return a string containing the binary 
> representation of x. For example, if x is a Python float, "tostring(x)" 
> would have eight characters. "fromstring(s, atype)" does the reserve, so
>      fromstring(tostring(x), type(x)) == x

For floats:
  struct.pack("d",...)
  struct.unpack("d",...)
For 32-bit signed integers:
  struct.pack("l",...)
  struct.unpack("l",...)
For 64 bit signed integers:
  struct.pack("Q",...)
  struct.unpack("Q",...)

Heck, you can even get big-endian output on little-endian machines (or
vv.) if you want!  Or you can toss the signs on the integers, get shorts,
or even chars.

Python already has such functionality in the standard library, though
perhaps it isn't the most aptly named (being in 'struct' rather than a
'value_packing' module...though its functionality was for packing and
unpacking of c-style structs...).


Alternatively, you can create an array (using similar typecodes), and
use the .tostring() and .fromstring() mechanism.

> 4. Add some functions that process floating point types at a low level. 
> I suggest borrowing from C
>      (mantissa, exponent) = frexp(x)

What about the sign?  Here's an implementation for you that includes the
sign...

def frexp(f):
    if not isinstance(f, float):
        raise TypeError, "Requires float argument"
    
    v, = struct.unpack(">Q", struct.pack(">d", f))
    #we ignore denormalized values, NANs, and infinities...
    return v>>63, 1 + (v&(2**52-1))/(2.0**52), ((v>>52)&2047)-1023


Is that enough?  Or did you want to convert back into a float?

def inv_frexp(sign, mantissa, exponent):
    #I don't know what this is normally called in C...
    v = bool(sign)*2**63
    v += (abs(int(exponent+1023))&2047)*2**52
    v += abs(int(((mantissa-1)*2**52)))&(2**52-1)
    
    f, = struct.unpack(">d", struct.pack(">Q", v))
    return f

Yeah, there's some bit work in there, and some is merely protection
against foolish inputs, but it's not that bad.

 - Josiah



More information about the Python-Dev mailing list