function "prratio()" in sources to BSD compress

Jonathan I. Kamens jik at athena.mit.edu
Thu Jun 7 12:36:16 AEST 1990


  (Note the Followup-To to comp.unix.wizards -- which one to go to is
pretty much a toss-up, so I chose the one I read. :-)

  In the BSD sources for the program compress (ucb/compress/compress.c),
there exists the following function:

    prratio(stream, num, den)
    FILE *stream;
    long int num, den;
    {
	    register int q;			/* Doesn't need to be long */

	    if(num > 214748L) {		/* 2147483647/10000 */
		    q = num / (den / 10000L);
	    } else {
		    q = 10000L * num / den;	/* Long calculations, though */
	    }
	    if (q < 0) {
		    putc('-', stream);
		    q = -q;
	    }
	    fprintf(stream, "%d.%02d%%", q / 100, q % 100);
    }

This function accomplishes using only integer arithmetic what the
following function accomplishes much more clearly, using floating point:

    prratio(stream, num, den)
    FILE *stream;
    long int num, den;
    {
	    double ratio;
	
	    ratio = (double) num / (double) den;

	    fprintf(stream, "%0.2f%%", ratio * 100.0);
    }

  Not only is the former function much less clear than the latter, the
former function screws up in some cases, while the latter one doesn't
(on a VAXstation 3100, for example, plugging in 905762 and 908964 for
num and den in both functions gives you 100.07% from the former
function, and 99.65% from the latter (the latter is correct).

  Keen observers will notice that the constant in the first function is,
of course, quite architecture-specific (or, at least, I think it is).  Sigh.

  My question is, WHY were things done as shown in the first example?  I
can think of several reasons, but I'm not able to convince myself 100%
that any of them were applicable when compress was written, and I'm even
less able to convince myself that any of them are applicable now :-). 
Some of the reasons I've thought of:

1. Integer arithmetic is faster.  Irrelevant when the function only gets
   called once or twice per compression, and that is the case here.

2. Some architectures don't have floating point arithmetic.  Yeah, right.

3. The floating point arithmetic on some architectures is so inaccurate that
   the code above produces better results.

Well, what do y'all think?  WHY was the function originally written as
shown in the first example above, and does it need to stay that way no,
especially since it produces incorrect results?

Jonathan Kamens			              USnail:
MIT Project Athena				11 Ashford Terrace
jik at Athena.MIT.EDU				Allston, MA  02134
Office: 617-253-8495			      Home: 617-782-0710



More information about the Comp.unix.wizards mailing list