From: Bob Law
Subject: floating decimal problem - new user
Date: 
Message-ID: <tjc8nvfq1sdh9c@corp.supernews.com>
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.

From: Kent M Pitman
Subject: Re: floating decimal problem - new user
Date: 
Message-ID: <sfwk821db5i.fsf@world.std.com>
"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.
From: Al Christians
Subject: Re: floating decimal problem - new user
Date: 
Message-ID: <3B36CA9A.8835CFD6@easystreet.com>
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
From: Al Christians
Subject: Re: floating decimal problem - new user
Date: 
Message-ID: <3B375D72.D3C6D81C@easystreet.com>
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
From: Raymond Toy
Subject: Re: floating decimal problem - new user
Date: 
Message-ID: <4nn16wfsfm.fsf@rtp.ericsson.se>
>>>>> "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!)
From: Raymond Toy
Subject: Re: floating decimal problem - new user
Date: 
Message-ID: <4n66dkfmb6.fsf@rtp.ericsson.se>
>>>>> "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
From: Al Christians
Subject: Re: floating decimal problem - new user
Date: 
Message-ID: <3B37B8FE.91CCBCA4@easystreet.com>
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
From: Gareth McCaughan
Subject: Re: floating decimal problem - new user
Date: 
Message-ID: <slrn9jfa2r.4lt.Gareth.McCaughan@g.local>
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
From: Christian Nyb�
Subject: Re: floating decimal problem - new user
Date: 
Message-ID: <ysskg0cprcyh.fsf@login-1.eunet.no>
"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
From: Arseny Slobodjuck
Subject: Re: floating decimal problem - new user
Date: 
Message-ID: <3b36d5d0.24487050@212.16.193.13>
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]>
From: Thomas A. Russ
Subject: Re: floating decimal problem - new user
Date: 
Message-ID: <ymin16wweq5.fsf@sevak.isi.edu>
"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    
From: Goldhammer
Subject: Re: floating decimal problem - new user
Date: 
Message-ID: <Qro27.444751$eK2.90784733@news4.rdc1.on.home.com>
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.
From: Raymond Toy
Subject: Re: floating decimal problem - new user
Date: 
Message-ID: <4nwv5hrfk6.fsf@rtp.ericsson.se>
>>>>> "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