[alt.sources] _doprint-less ftoa

istvan@hhb.UUCP (Istvan Mohos) (12/29/89)

In the absence of elegant solutions to the _doprint-less ftoa problem
posed by Marcus J. Ranum, here is a highly tedious one: convert the float
into two ulongs (one for the whole-number part and one for the fraction),
and break each one down to decimal digits.

As Simon & Garfunkel once said about floating point precision:
    "...any way you look at it, you loose."

-------------------------------CUT HERE--------------------------------
/* ftoa the hard way --- Istvan Mohos, 1989 --- in the Public Domain */
/* compile with: /bin/cc ftoa.c -lm -o ftoa */
/* assuming 32-bit longs */

#include <math.h>
#include <stdio.h>

/* bare-bones main just for testing --- no error checking */
main (argc, argv)
int argc;
char *argv[];
{
    char *ftoa();
    char str[512];

    while (gets (str) != NULL)
        puts (ftoa (atof (str)));
    exit (0);
}

char *
ftoa (fl)
float fl;
{
    static char buf[512];
    static long magtab[] =
        {0,1,10,100,1000,10000,100000,1000000,10000000,100000000,1000000000};
    float absfl = fabs (fl);
    char *ptr = buf;
    unsigned long ens;            /* "ones", "tens", "hundreds", etc. */
    unsigned long whole, fraction;
    int mag;                      /* magnitude */

    /* overflow error */
    if (absfl > 4294967296.) {
        *ptr = 0;
        return (buf);
    }

    /* break abs float into two ulongs; max fraction size may approach 1 bil */
    whole = ((unsigned long) absfl);
    fraction = (unsigned long)((absfl - whole) * 1000000000.);

#ifdef DEBUG
    printf ("whole:%ld, fraction:%ld\n", whole, fraction);
#endif

    /* negative? */
    if (fl < 0.)
        *ptr++ = '-';

    /* print whole, beginning at most significant decimal digit */
    if (whole == 0L)
        *ptr++ = '0';
    else {
        for (mag = 2; mag < 11; mag++) {
            if (magtab[mag] > whole)
                break;
        }
        for (; --mag; whole -= ens * magtab[mag]) {
            ens = whole / magtab[mag];
            *ptr++ = ens + '0';
        }
    }

    *ptr++ = '.';

    /* print fraction, retaining leading zeros */
    for (mag = 10; --mag; fraction -= ens * magtab[mag]) {
        ens = fraction / magtab[mag];
        *ptr++ = ens + '0';
    }

    /* blank trailing zeros */
    while (*--ptr == '0');
    *++ptr = 0;
    return (buf);
}
-------------------------------CUT HERE--------------------------------
-- 
        Istvan Mohos
        ...uunet!pyrdc!pyrnj!hhb!istvan
        HHB Systems 1000 Wyckoff Ave. Mahwah NJ 07430 201-848-8000
====================================================================