I'm trying to learn lisp using clisp and it is quite disheartening to find
that
(+ 3.14 2.71)
returns 5.8500004.
That is news to me! I'm sure it has something to due with the binary
representation of decimals. I contacted their site at sourceforge.net and
they replied that I needed to user doubles for greater precision and should
look up *read-default-float-format* in the CLHS.
*read-default-float-format* returns single-float.
How do I change that so that my math is correct? I have not idea what CLHS
is.
"Bob Law" <····@rcsis.com> writes:
> I'm trying to learn lisp using clisp and it is quite disheartening to find
> that
> (+ 3.14 2.71)
> returns 5.8500004.
> That is news to me! I'm sure it has something to due with the binary
> representation of decimals. I contacted their site at sourceforge.net and
> they replied that I needed to user doubles for greater precision and should
> look up *read-default-float-format* in the CLHS.
> *read-default-float-format* returns single-float.
>
> How do I change that so that my math is correct? I have not idea what CLHS
> is.
The math *is* correct.
You need to learn a lot about floats probably to understand the
details but the take-home message you should get right now is that
floats are binary approximations, *not* decimal approximations. Use
the FORMAT operators that do rounding for display purposes if you plan
to do a small number of computations and you just want the answer to
"look nice"; if you're doing math for money, or something else that
requires decimal precision, you probably want to use COBOL or create a
data structure in Lisp based on integer numbers of pennies or tenths
of pennies. This has all been recently discussed on this newsgroup,
so try poking around in Deja News.
CLHS is the Common Lisp HyperSpec. It is an online hypertext which is a
derivative document of the ANSI Common Lisp specification, the language
definition to which all vendors adhere.
I'm pretty sure, by the way, that all modern languages that conform to
IEEE arithmetic standards are going to have the same kinds of effects as
Lisp has when dealing with float datatypes. I don't think your problem
is at all at the language-level. The very machine instructions of most
computers you're using are what are producing this result.
Kent M Pitman wrote:
>
> "Bob Law" <····@rcsis.com> writes:
>
> > I'm trying to learn lisp using clisp and it is quite disheartening to find
> > that
> > (+ 3.14 2.71)
> > returns 5.8500004.
> > That is news to me! I'm sure it has something to due with the binary
>
> The math *is* correct.
>
But if you do this first:
(setq *read-default-float-format* 'double-float)
Then
(+ 3.14 2.71) returns 5.85.
(from clisp-2.26) Using double floats will still produce a roundoff
error, but it is much smaller, and somehow, I suppose, the program
guesses that we are not interested in the details of the 18th
or 19th significant digit. IDK how.
Al
From: Tim Bradshaw
Subject: Re: floating decimal problem - new user
Date:
Message-ID: <nkjofrchm2u.fsf@tfeb.org>
Al Christians <·······@easystreet.com> writes:
> (from clisp-2.26) Using double floats will still produce a roundoff
> error, but it is much smaller, and somehow, I suppose, the program
> guesses that we are not interested in the details of the 18th
> or 19th significant digit. IDK how.
It is more likely the case that the numbers and their sum have an
accurate representation as doubles.
--tim
Tim Bradshaw wrote:
>
> Al Christians <·······@easystreet.com> writes:
>
> > (from clisp-2.26) Using double floats will still produce a roundoff
> > error, but it is much smaller, and somehow, I suppose, the program
> > guesses that we are not interested in the details of the 18th
> > or 19th significant digit. IDK how.
>
> It is more likely the case that the numbers and their sum have an
> accurate representation as doubles.
>
Yes. Accurate, but not exact.
We see:
> (setq *read-default-float-format* 'long-float)
LONG-FLOAT
> (+ 3.14 2.71)
5.8500000000000000003
> (setq *read-default-float-format* 'double-float)
DOUBLE-FLOAT
> (+ 3.14 2.71)
5.85
It looks like when the *read-default-float-format* is DOUBLE-FLOAT,
sixteen places are shown. When it is LONG-FLOAT, we've got 20 places,
SINGLE-FLOAT gives eight. (In each case, any trailing zeroes are
not displayed) The choice for number of decimal digits to show is a
little arbitrary, since the numbers are binary internally. It works
out that the typical round-off error is more often hidden for doubles
than for single or long -- the double data type is almost good to 17
places, so the roundoff is often not seen with only sixteen digits
shown. For single or long, the roundoff discrepancies will usually
be apparent, as the internal representations don't use quite enough
bits for 8 or 20 digits.
(All of that is exactly what Tim Bradshaw said so succinctly)
Al
From: Tim Bradshaw
Subject: Re: floating decimal problem - new user
Date:
Message-ID: <nkju214o8ot.fsf@tfeb.org>
Al Christians <·······@easystreet.com> writes:
>
> It looks like when the *read-default-float-format* is DOUBLE-FLOAT,
> sixteen places are shown. When it is LONG-FLOAT, we've got 20 places,
> SINGLE-FLOAT gives eight. (In each case, any trailing zeroes are
> not displayed) The choice for number of decimal digits to show is a
> little arbitrary, since the numbers are binary internally. It works
> out that the typical round-off error is more often hidden for doubles
> than for single or long -- the double data type is almost good to 17
> places, so the roundoff is often not seen with only sixteen digits
> shown. For single or long, the roundoff discrepancies will usually
> be apparent, as the internal representations don't use quite enough
> bits for 8 or 20 digits.
Incidentally I think it's quite unusual to have a system with more
than two different representations for floats. CLISP does seem to
have a multittude though.
--tim
>>>>> "Tim" == Tim Bradshaw <···@tfeb.org> writes:
Tim> Al Christians <·······@easystreet.com> writes:
>>
>> It looks like when the *read-default-float-format* is DOUBLE-FLOAT,
>> sixteen places are shown. When it is LONG-FLOAT, we've got 20 places,
>> SINGLE-FLOAT gives eight. (In each case, any trailing zeroes are
>> not displayed) The choice for number of decimal digits to show is a
>> little arbitrary, since the numbers are binary internally. It works
>> out that the typical round-off error is more often hidden for doubles
>> than for single or long -- the double data type is almost good to 17
>> places, so the roundoff is often not seen with only sixteen digits
>> shown. For single or long, the roundoff discrepancies will usually
>> be apparent, as the internal representations don't use quite enough
>> bits for 8 or 20 digits.
Tim> Incidentally I think it's quite unusual to have a system with more
Tim> than two different representations for floats. CLISP does seem to
Tim> have a multittude though.
Clisp supports all 4 types specified in CL. And also has the
interesting feature that long-float can be dynamically changed to be
whatever (reasonable) size you want. I've used it for 128- and
256-bit floats, just for fun.
Ray
From: Tim Bradshaw
Subject: Re: floating decimal problem - new user
Date:
Message-ID: <nkjpubszdtu.fsf@tfeb.org>
Raymond Toy <···@rtp.ericsson.se> writes:
>
> Clisp supports all 4 types specified in CL. And also has the
> interesting feature that long-float can be dynamically changed to be
> whatever (reasonable) size you want. I've used it for 128- and
> 256-bit floats, just for fun.
>
Presumably it doesn't have very fast FP stuff, or are some of the
types implemented in such a way that they correspond to the machine
types?
--tim (this isn't a complaint abot CLISP!)
>>>>> "Tim" == Tim Bradshaw <···@tfeb.org> writes:
Tim> Raymond Toy <···@rtp.ericsson.se> writes:
>>
>> Clisp supports all 4 types specified in CL. And also has the
>> interesting feature that long-float can be dynamically changed to be
>> whatever (reasonable) size you want. I've used it for 128- and
>> 256-bit floats, just for fun.
>>
Tim> Presumably it doesn't have very fast FP stuff, or are some of the
Tim> types implemented in such a way that they correspond to the machine
Tim> types?
I'm pretty sure single-float and double-float are implemented via HW
for those platforms that have it IEEE FP. Presumably the short and
long float types are all in software, but I don't know for sure.
Ray
Raymond Toy wrote:
>
> >>>>> "Tim" == Tim Bradshaw <···@tfeb.org> writes:
>
> Tim> Raymond Toy <···@rtp.ericsson.se> writes:
> >>
> >> Clisp supports all 4 types specified in CL. And also has the
> >> interesting feature that long-float can be dynamically changed to be
> >> whatever (reasonable) size you want. I've used it for 128- and
> >> 256-bit floats, just for fun.
> >>
>
> Tim> Presumably it doesn't have very fast FP stuff, or are some of the
> Tim> types implemented in such a way that they correspond to the machine
> Tim> types?
>
> I'm pretty sure single-float and double-float are implemented via HW
> for those platforms that have it IEEE FP. Presumably the short and
> long float types are all in software, but I don't know for sure.
There is a 10-byte floating point type on Intel x86 machines. This
has 64-bits of mantissa (unlike the other formats, the most significant
bit is shown explicitly; IDK if it can be zero). This is enough for
about 19+ places of decimal accuracy, so I'm guessing that's what I'm
seeing as 20-place long-float.
Al
From: Tim Bradshaw
Subject: Re: floating decimal problem - new user
Date:
Message-ID: <nkjhex34kiz.fsf@tfeb.org>
Al Christians <·······@easystreet.com> writes:
> There is a 10-byte floating point type on Intel x86 machines. This
> has 64-bits of mantissa (unlike the other formats, the most significant
> bit is shown explicitly; IDK if it can be zero). This is enough for
> about 19+ places of decimal accuracy, so I'm guessing that's what I'm
> seeing as 20-place long-float.
>
It might be, but types like that exist on CLISPs compiled on other
architectures too, so there must be a portble version as well.
--tim
Tim Bradshaw wrote:
[Raymond Toy:]
> > Clisp supports all 4 types specified in CL. And also has the
> > interesting feature that long-float can be dynamically changed to be
> > whatever (reasonable) size you want. I've used it for 128- and
> > 256-bit floats, just for fun.
>
> Presumably it doesn't have very fast FP stuff, or are some of the
> types implemented in such a way that they correspond to the machine
> types?
SINGLE-FLOAT and DOUBLE-FLOAT in CLISP are just what you
might expect them to be. Of course, few things in CLISP
are "very fast". :-)
(Note: yes, I know CLISP's bignum arithmetic is very good.
I said "few", not "no"...)
--
Gareth McCaughan ················@pobox.com
.sig under construc
"Bob Law" <····@rcsis.com> writes:
> I have not idea what CLHS is.
It's the Common Lisp Hyperspec, found at
<URL:http://www.xanalys.com/software_tools/reference/HyperSpec/>
--
chr
On Sun, 24 Jun 2001 10:36:56 -0700, "Bob Law" <····@rcsis.com> wrote:
>I'm trying to learn lisp using clisp and it is quite disheartening to find
>that
>(+ 3.14 2.71)
>returns 5.8500004.
>That is news to me! I'm sure it has something to due with the binary
>representation of decimals. I contacted their site at sourceforge.net and
>they replied that I needed to user doubles for greater precision and should
>look up *read-default-float-format* in the CLHS.
>*read-default-float-format* returns single-float.
Special variable (global variable) named *read-default-float-format*
holds a value, defining the type of floats which are read by 'reader'.
You may read CLHS to know what the reader is. By default, floats are
read as short-floats and that's approximately corresponds this error
of 0.0000004.
look:
[2]> (+ 3.14 2.71)
5.8500004
[3]> (setf *read-default-float-format* 'double-float)
DOUBLE-FLOAT
[4]> (+ 3.14 2.71)
5.85
[5]>
"Bob Law" <····@rcsis.com> writes:
>
> I'm trying to learn lisp using clisp and it is quite disheartening to find
> that
> (+ 3.14 2.71)
> returns 5.8500004.
> That is news to me! I'm sure it has something to due with the binary
> representation of decimals.
Congratulations on figuring out the reason behind this! Most new
programmers are completely clueless about the representation and round
off issue.
> How do I change that so that my math is correct? I have not idea what CLHS
> is.
Well, if you insist on using floating point numbers on binary computers,
you need to only use binary fractions: x.5 x.25 x.125 etc.
However, Lisp does give you another alternative. You can use rational
numbers, which will give you the exact answer:
(+ 314/100 271/100) => 117/20
If you really need to do the arithmetic with input as floats, you can
still arrange (with a bit of work) to do the actual computation with
rationals and only convert at the end:
(defun my+ (x y)
(float (+ (rationalize x) (rationalize y))))
(my+ 3.14 2.71) => 5.85
--
Thomas A. Russ, USC/Information Sciences Institute ···@isi.edu
On Sun, 24 Jun 2001 10:36:56 -0700, Bob Law <····@rcsis.com> wrote:
>I'm trying to learn lisp using clisp and it
>is quite disheartening to find that
>(+ 3.14 2.71)
>returns 5.8500004.
>That is news to me! I'm sure it has something to due with the binary
>representation of decimals.
>How do I change that so that my math is correct?
(+ 3.14d0 2.71d0)
--
Don't think you are. Know you are.
>>>>> "Goldhammer" == Goldhammer <··········@my-deja.com> writes:
Goldhammer> On Sun, 24 Jun 2001 10:36:56 -0700, Bob Law <····@rcsis.com> wrote:
>> I'm trying to learn lisp using clisp and it
>> is quite disheartening to find that
>> (+ 3.14 2.71)
>> returns 5.8500004.
>> That is news to me! I'm sure it has something to due with the binary
>> representation of decimals.
>> How do I change that so that my math is correct?
Goldhammer> (+ 3.14d0 2.71d0)
That just hides the problem because you're just lucky that the reader
and printer rounds things to the value you expected.
I think the right way should be (+ 314/100 271/100) => 117/20. :-)
Ray