[erlang-questions] Any way to correct the round off errors?

Witold Baryluk baryluk@REDACTED
Sun Sep 20 17:22:11 CEST 2009


Dnia 2009-09-20, nie o godzinie 15:02 +0100, Richard Kelsall pisze:
> > When subtracting in Erlang: 0.92915-0.92945 we should get -0.0003 but Erlang
> > gives: -2.9999999999996696e-4   (when doing 92915-92945 Erlang gives -30 so
> > that's ok).
> > 
> > Anyway to make make it give -0.0003 ?, and in general make it give more
> > accurate answers?
> 
> That's an interesting question. The other replies tell us it's a 64 bit
> Double floating point representation :
> 
> http://en.wikipedia.org/wiki/Double_precision_floating-point_format
> 
> which has, according to Wikipedia, "about 16 decimal digits" of
> precision from the 52 bits. Their example is correct up to 16 digits :
> 
> 0.33333333333333331482
>                   *
>    1234567890123456
> 
> but yours is only correct up to 13 digits :
> 
> 2.9999999999996696e-4
>               *
> 1 234567890123456

Wikipedia says that it have about 16 decimal digits (52 or 53 binary
digits), but it says nothing about how many of them are correct.
Information about 16 digits is only providad because ie. printing more
than 16 decimal digits doesn't provide any more information (rest of
digits after 53 is just zeros, and after converting them to decimal they
just some "random" digits, completly insignificant [after converting
back to binary they are smaller than 2^-53 anyway, so efectively 0.0).

> 
> so we probably shouldn't trust more than 12 digits of precision because
> each calculation will lose some precision from the end of the number.
Substraction (and addition) can lose  any number of digits you wish.


> Different calculations will lose different amounts of precision and
> very long sequences of calculations could reduce the number of correct
> digits below 12.
Yep.

> You might think it would be nice to have every calculation keep a record
> in the double of how many digits we can trust.
It is called interval methods. They are very robust. Can be connected
with other techniques for fast and accurate (with 100% certainity)
calculations.


>  If we did this the output
> routine could give the exact answer to your calculation. But this would
> be very difficult to calculate and would consume processor power at
> every step. So instead floating point routines rely on the programmer
> to know about floating point accuracy and you always have to round the
> output appropriately. If you round that answer to 12 digits it is
> exactly correct.
> 
> In general always use a number representation that can cope with numbers
> much bigger and with much more accuracy than you are expecting because
> bugs in this area are nasty.

It all depends what you want. Floating point number are just tricky.

both 0.92915 and 0.92945 are already not representable as binary
floating point numbers:

> io:format("~.30f~n", [0.92915]).
0.929150000000000031442000000000
> 
5> io:format("~.30f~n", [0.92945]).
0.929449999999999998401000000000
ok



If you want something which calculates correctly in decimal number, use
integers multiplied with some 10^k power. It is called fixed point
arithmetic.


-- 
Witold Baryluk
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 198 bytes
Desc: To jest cz??? wiadomo?ci podpisana cyfrowo
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20090920/811e75a3/attachment.bin>


More information about the erlang-questions mailing list