Path: gmdzi!unido!mcsun!uunet!tut.cis.ohio-state.edu!zaphod.mps.ohio-state.edu!
usc!snorkelwacker!bloom-beacon!athena.mit.edu!jik
From: j...@athena.mit.edu (Jonathan I. Kamens)
Newsgroups: comp.unix.wizards,comp.lang.c
Subject: function "prratio()" in sources to BSD compress
Message-ID: <1990Jun7.023616.25034@athena.mit.edu>
Date: 7 Jun 90 02:36:16 GMT
Sender: n...@athena.mit.edu (News system)
Reply-To: j...@athena.mit.edu (Jonathan I. Kamens)
Followup-To: comp.unix.wizards
Organization: Massachusetts Institute of Technology
Lines: 70
Posted: Thu Jun  7 03:36:16 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
j...@Athena.MIT.EDU				Allston, MA  02134
Office: 617-253-8495			      Home: 617-782-0710

Path: gmdzi!unido!mcsun!uunet!snorkelwacker!apple!agate!riacs!jaw
From: j...@riacs.edu (James A. Woods)
Newsgroups: comp.unix.wizards
Subject: Re: function "prratio()" in sources to BSD compress
Message-ID: <1990Jun7.184525.962@riacs.edu>
Date: 7 Jun 90 18:45:25 GMT
References: <1990Jun7.023616.25034@athena.mit.edu>
Organization: RIACS, NASA Ames Research Center
Lines: 13
Posted: Thu Jun  7 19:45:25 1990

good eye.
the original was floating point, like your suggestion, and
i wrote it knowing the floats were not a cpu drain.

it was changed by ken turkowski (still of apple?) to accomodate
a pdp 11 without floating point hardware.

i agree that it should revert to floating point.

better yet would be to speedup dan bernstein's 'squeeze',
a miller/wegman/ziv/lempel coder which has better c-rates. 

ames!jaw