Next float?

Alex Holkner alex.holkner at gmail.com
Wed Nov 21 23:26:05 EST 2007


On Nov 22, 2007 2:04 PM, Steven D'Aprano
<steven at remove.this.cybersource.com.au> 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



More information about the Python-list mailing list