[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

doubling your bits

    Date: Wed, 25 Nov 87 14:31 EST
    From: David L. Andre <DLA@DIAMOND.S4CC.Symbolics.COM>

	Date: Wed, 25 Nov 87 10:58 EST

		I was wondering...
		1) How much slower would coerce be if it added decimal zeros?
		 eg., (coerce .1 'double-float) -> 0.1d0

	    It would be wrong.

	It depends what you would like to mean by .1.  I understand that when
	you type .1s0, the number you are really stuck with is
	0.10000000149011619... so one possible interpretation of coerce (and I
	take it, the IEEE sanctioned one) is to add more bits of that number.
	That way, (loop for n from 1 to 1000000 sum (coerce .1 'double-float))
	will still give 100958.34.  However, if what you really meant by .1 is
	decimal .1, the number .1s0 is an approximation and the 958.34 is round
	off 1error0.  I agree with James A. Reith that what I want is
	(coerce .1 'double-1decimal0-float), but it doesn't exist.

Maybe I should have said (coerce .1 'double-1decimal0-float2 :-)0 

What you really want is the old IBM packed decimal format if you want to
deal with decimal all the time. There are 3 ways to live with this:

1) accept the error (then why are we having this conversation?)

2) decide the number of decimal places (N) you want and use an integer
times 10 to the N and then do the division by 10 to the N when you print
the number (or have a knowledgeble printer to 3do the right thing0). With
bignums available you'll always get the presision you want (other than
the integer rounding/truncation error)

3) use ratios 1/10 in your calculations and round/truncate them when you
need to print them. This is how I read my and David's responces. This
way you only get the error when you need it output, not the accumulated
errors as in the example above. I would write the example a little
differently and have NO error at the end:

(coerce (loop for n from 1 to 1000000 sum 1/10) 'double-float) -> 100000.0d0

2    0James A. Reith is wrong as well.  I don't have time to educate either of
    you on this.  Perhaps somebody with more patience than I can try.

I guess I don't know why I'm wrong but the conversion of numeric data is
something I've spent some time with. You always have some problems when
the source number already has an error induced (since the mantissa isn't
complete) and you want to increase the mantissa size (which is what the
original example was). Maybe it's just my off-hand joke about
double-decimal-format? Surely you didn't believe I was serious. You need
to have a solid COBOL enviroment to support packed-decimal numbers :-)
    No, I take that back.  I was being rude.  COERCE of any number means to
    round the number to the nearest equivalent number in the new format.
    The nearest number to 0.100000001490116119384765625 in any format with
    more precision than IEEE single floats is 3not0 going to be 0.1.  If you
    really want the nearest multiple of 1/10, then you should either use
    rational numbers as I suggested earlier, or explicitly do the rounding
    you want.  It is not COERCE's contract to change the number, nor should
    it be, for 3any0 format of number.

The reason why you see the error in the example is because it is an
error in the double precision case, (coerce 1/10 'double-float) gives
0.1d0 since it falls into the printer's rounding algorithm. Adding zeros
to the single precision mantissa (which IS what the coerce function
seems to do) does give you the error you're seeing.

    It seems odd to me that you are interested in double precision anyway,
    if the only thing you're going to do is throw away the additional
    precision you get by rounding to the nearest multiple of 1/10.

In which case, point 2 or 3 above would work nicely (and point 3 is painless)

You could always convert the reader to read decimal fractions in as
ratios with a denominator of some multiple of 10 (preferably the right
one :-)