[Openmcl-devel] Floating point precision
Brian Mastenbrook
brian at mastenbrook.net
Sat Jan 17 18:39:45 PST 2009
On Jan 17, 2009, at 8:18 PM, Sudhir Shenoy wrote:
> Yes, this is true for currency related calculations (interest, tax,
> etc.) and most accounting packages use BCD arithmetic as a result.
>
> What I am doing, however, is valuation of complex instruments (options
> and other derivatives) where you need double floats because, mostly,
> you are working with probability distributions and other irrational
> numbers such as natural logarithms. Inputs to the program from the
> external world can be coerced to double-float by default but I was
> unaware that conversions from integers or rationals to float would
> always use single-float instead of double as per the standard. I now
> have to go through the code and ensure that all constants are affixed
> with 'd0' even where they are exact integers because of the danger of
> intermediate results losing precision if these constants are passed to
> math functions ...
Makes sense. Sorry for the noise; an alarming number of programmers
I've talked to in the past don't know *not* to use binary floats for
currency calcuations.
> It is a pity that there is no analogue to *read-default-float-format*
> to specify this conversion rule. I guess that when the standard was
> written, floating point calculations were deemed to be expensive and
> the coming of cheap and fast floating point processors wasn't foreseen
> (or maybe all scientific computation at the time used FORTRAN
> anyhow :-).
>
> Would it be a good idea to introduce a special variable in the CCL
> package, e.g. *float-substitute-target*, that would default to
> 'single-
> float but could be set to 'double-float if required (and introduce a
> conditional in all places that an int->float conversion is performed)?
It is possible to do something like this in user code. Create a new
package (say, DOUBLE-LISP) that imports all symbols from COMMON-LISP
but the numeric operations (given in a list in the spec at http://www.lispworks.com/documentation/HyperSpec/Body/12_aa.htm)
, and exports all symbols that the COMMON-LISP package exports. For
each of the numeric operations (at least the ones that take and
necessarily return float arguments), create a dummy wrapper that
coerces any rational arguments to double-float before calling the real
CL function. As you've already noted, you should set *read-default-
float-format* so that single floats never enter your program.
Then, simply use DOUBLE-LISP instead of COMMON-LISP in your user code.
I hate to suggest this on a CCL mailing list, but may want to consider
using CLISP, which has long floats with user-specified precision.
Additionally there is a user switch to change the float contagion mode
to one which (in my opinion) is significantly saner. In ANSI CL, the
result of an operation involving a single-float and double-float is
specified to be a double-float, but this simply tricks the user into
believing that more significant information is available in the result
than is really there. In the optional CLISP mode, contagion is from
most-specific to least-specific, so that the result never claims to be
more accurate than it really is.
Unfortunately I don't believe the optional mode affects the rule of
float substitutability, which is what is causing e.g. (sqrt 1/3) to
return a single-float. For that, you would still need a custom
package. (Aha, I see that Raffael Cavallaro has beaten me to the bunch
as I'm typing this!)
--
Brian Mastenbrook
brian at mastenbrook.net
http://brian.mastenbrook.net/
More information about the Openmcl-devel
mailing list