On Nov 22, 2007 2:04 PM, Steven D'Aprano
<[EMAIL PROTECTED]> wrote:
> Is there a simple, elegant way in Python to get the next float from a
> given one? By "next float", I mean given a float x, I want the smallest
> float larger than x.
>
> Bonus points if I can go in either direction (i.e. the "previous float"
> as well as the next).

Not so elegant, but you could use ctypes to manipulate the bits
(assumes machine uses IEEE 754 doubles for Python floats, I'm not sure
if that's guaranteed on esoteric platforms):

import ctypes

def inc_float(f):
    # Get an int64 pointer to the float data
    fv = ctypes.c_double(f)
    pfv = ctypes.pointer(fv)
    piv = ctypes.cast(pfv, ctypes.POINTER(ctypes.c_uint64))

    # Check for NaN or infinity, return unchanged
    v = piv.contents.value
    if not ~(v & (11 << 52)): # exponent is all 1's
        return f

    if v == 1 << 63:    # -0, treat as +0
        v = 1
    elif v & (1 << 63): # negative
        v -= 1
    else:               # positive or +0
        v += 1

    # Set int pointer and return changed float
    piv.contents.value = v
    return fv.value

def dec_float(f):
    # Get an int64 pointer to the float data
    fv = ctypes.c_double(f)
    pfv = ctypes.pointer(fv)
    piv = ctypes.cast(pfv, ctypes.POINTER(ctypes.c_uint64))

    # Check for NaN or infinity, return unchanged
    v = piv.contents.value
    if not ~(v & (11 << 52)): # exponent is all 1's
        return f

    if v == 0:          # +0, treat as -0
        v = (1 << 63) | 1
    elif v & (1 << 63): # negative
        v += 1
    else:               # positive
        v -= 1

    # Set int pointer and return changed float
    piv.contents.value = v
    return fv.value
-- 
http://mail.python.org/mailman/listinfo/python-list

Reply via email to