floor() function and mathematical integers

Aahz Maruch aahz at panix.com
Fri May 25 12:23:38 EDT 2001


In article <3b0e6e65.279481372 at wa.news.verio.net>,
Bengt Richter <bokr at accessone.com> wrote:
>
>Decided to add fractional float bit printing. Just started playing
>with Python, as you can probably tell. No warranty.

For comparison, take a look at this routine from Tim Peters to convert
floats to strings (yes, Tim, I modified it to work with 1.5.2):

def _floatToString(x):
    """Return float x as exact decimal string.

    The string is of the form:
        "-", if and only if x is < 0.
        One or more decimal digits.  The last digit is not 0 unless x is 0.
        "e"
        The exponent, a (possibly signed) integer
    """

    import math
    # XXX ignoring infinities and NaNs for now.

    if x == 0:
        return "0e0"

    sign = ""
    if x < 0:
        sign = "-"
        x = -x

    f, e = math.frexp(x)
    assert 0.5 <= f < 1.0
    # x = f * 2**e exactly

    # Suck up CHUNK bits at a time; 28 is enough so that we suck
    # up all bits in 2 iterations for all known binary double-
    # precision formats, and small enough to fit in an int.
    CHUNK = 28
    top = 0L
    # invariant: x = (top + f) * 2**e exactly
    while f:
        f = math.ldexp(f, CHUNK)
        digit = int(f)
        assert digit >> CHUNK == 0
        top = (top << CHUNK) | digit
        f = f - digit
        assert 0.0 <= f < 1.0
        e = e - CHUNK
    assert top > 0

    # Now x = top * 2**e exactly.  Get rid of trailing 0 bits if e < 0
    # (purely to increase efficiency a little later -- this loop can
    # be removed without changing the result).
    while e < 0 and top & 1 == 0:
        top = top >> 1
        e = e + 1

    # Transform this into an equal value top' * 10**e'.
    if e > 0:
        top = top << e
        e = 0
    elif e < 0:
        # Exact is top/2**-e.  Multiply top and bottom by 5**-e to
        # get top*5**-e/10**-e = top*5**-e * 10**e
        top = top * 5L**-e

    # Nuke trailing (decimal) zeroes.
    while 1:
        assert top > 0
        newtop, rem = divmod(top, 10L)
        if rem:
            break
        top = newtop
        e = e + 1

    return "%s%de%d" % (sign, top, e)



More information about the Python-list mailing list