[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
From: Bill Long <WJL@ZERMATT.LCS.MIT.EDU>
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 :-)