From: Aravindh Johendran on
I'm working on an exercise in SICP - improving the square root program
in the first chapter. Exercise 1.7, to be precise.

In MIT-Scheme, if I define average to be as follows,
(define (average x y)
(/ (+ x y) 2))

Why are the following incantations not giving me the correct/expected
answers?

(+ 0.9999999999999999e23 1.0000000000000001e23)
;Value: 1.9999999999999998e23

(average 0.9999999999999999e23 1.0000000000000001e23)
;Value: 0.9999999999999999e23

Is all of this related to floating point arithmetic? Is there a good
source to understand the topic? Wikipedia entry is dense.
I hate SICP. One seemingly innocuous question in an exercise about
square roots in the first chapter and it is taking me days to answer.

---------------------------------------------------

Whereas, in Common Lisp (CCL, SBCL and CLISP)

CL-USER> (defun avg (x y)
(/ (+ x y) 2))
AVG
CL-USER> (avg 9.999999999999999E22 1.0000000000000001E23)
1.0E23
CL-USER> 9.999999999999999E22
1.0E23
CL-USER> 1.0000000000000001E23
1.0E23
CL-USER> (describe 0.9999999999999999e23) ;; CCL version
Float: 1.0E+23
Scientific: 1.00E+23
Log base 2: 76.40434
Ratio equiv: 99999997781963083612160
Nearest integer: 99999997781963083612160
----------------------------------------------------------

Why is CL behavior different? Is rounding off done automatically
according to the specs? Even though I entered 0.9999999999999999e23 in
the REPL, the genie refers to it as 1.0E+23. Where did it get
modified? While it was being read in?

From: Tamas K Papp on
On Mon, 03 May 2010 00:04:03 -0700, Aravindh Johendran wrote:

> I'm working on an exercise in SICP - improving the square root program
> in the first chapter. Exercise 1.7, to be precise.
>
> In MIT-Scheme, if I define average to be as follows, (define (average x
> y)
> (/ (+ x y) 2))
>
> Why are the following incantations not giving me the correct/expected
> answers?
>
> (+ 0.9999999999999999e23 1.0000000000000001e23) ;Value:
> 1.9999999999999998e23
>
> (average 0.9999999999999999e23 1.0000000000000001e23) ;Value:
> 0.9999999999999999e23
>
> Is all of this related to floating point arithmetic? Is there a good
> source to understand the topic? Wikipedia entry is dense. I hate SICP.
> One seemingly innocuous question in an exercise about square roots in
> the first chapter and it is taking me days to answer.
>
> ---------------------------------------------------
>
> Whereas, in Common Lisp (CCL, SBCL and CLISP)
>
> CL-USER> (defun avg (x y)
> (/ (+ x y) 2))
> AVG
> CL-USER> (avg 9.999999999999999E22 1.0000000000000001E23) 1.0E23
> CL-USER> 9.999999999999999E22
> 1.0E23
> CL-USER> 1.0000000000000001E23
> 1.0E23
> CL-USER> (describe 0.9999999999999999e23) ;; CCL version Float: 1.0E+23
> Scientific: 1.00E+23
> Log base 2: 76.40434
> Ratio equiv: 99999997781963083612160
> Nearest integer: 99999997781963083612160
> ----------------------------------------------------------
>
> Why is CL behavior different? Is rounding off done automatically
> according to the specs? Even though I entered 0.9999999999999999e23 in
> the REPL, the genie refers to it as 1.0E+23. Where did it get modified?
> While it was being read in?

CL will read these as single floats by default:

CL-USER> (defparameter *f* 9.999999999999999E22)
*F*
CL-USER> *f*
1.e23
CL-USER> (float-radix *f*)
2
CL-USER> (float-precision *f*)
24

As you see, there aren't enough digits in there to represent the
numbers you are using as something different from 1. You might want
to use double floats: the syntax is 1.0000000000000001d23. But then
again, you are at the very limit of machine precision:

CL-USER> (- 1.0000000000000001d23 1d23)
1.6777216d7

Use rationals if you want these kind of calculations to be precise.

The article by Goldberg [1] is a good intro to floating point
arithmetic. There are zillion copies floating around on the net, just
grab one, but be advised that it is not an easy topic. If you are
just learning Lisp, I would suggest that you ignore this issue and
come back to it later, if/when you are doing serious numerical
computation.

Best,

Tamas

[1] http://portal.acm.org/citation.cfm?id=103163
From: Pascal J. Bourguignon on
Tamas K Papp <tkpapp(a)gmail.com> writes:

> On Mon, 03 May 2010 00:04:03 -0700, Aravindh Johendran wrote:
>
>> I'm working on an exercise in SICP - improving the square root program
>> in the first chapter. Exercise 1.7, to be precise.
>>
>> In MIT-Scheme, if I define average to be as follows, (define (average x
>> y)
>> (/ (+ x y) 2))
>>
>> Why are the following incantations not giving me the correct/expected
>> answers?
>>
>> (+ 0.9999999999999999e23 1.0000000000000001e23) ;Value:
>> 1.9999999999999998e23
>>
>> (average 0.9999999999999999e23 1.0000000000000001e23) ;Value:
>> 0.9999999999999999e23
>>
>> Is all of this related to floating point arithmetic?

Yes.

> Use rationals if you want these kind of calculations to be precise.


>> Is there a good source to understand the topic?

Yes:
> The article by Goldberg [1] is a good intro to floating point
> arithmetic.
> [1] http://portal.acm.org/citation.cfm?id=103163

or:

http://docs.sun.com/source/806-3568/ncg_goldberg.html


> [...] just grab one, but be advised that it is not an easy topic If you are
> just learning Lisp, I would suggest that you ignore this issue and
> come back to it later, if/when you are doing serious numerical
> computation.

Well, it's not difficult to understand the problem. What's not easy
is to solve it adequately. This is where numerical algorithmic
wizzardry comes in.

But understanding the problem is easy, it is taught to pupil at the
end of primary school:

Divide 1 by 3 with 4 digits of precision.
You get 0.3333

Now, add three times this (approximate) value of 1/3:

0.3333
+ 0.3333
+ 0.3333
--------
0.9999

and subtract it from 1:

1
- 0.9999
--------
0.00001

which is, using 4 digits of precision:

0.0000

But, if you use floating point, instead of fixed point, then 0.00001
is written 1e-5, and there is no rounding (there's only one
significant digit here).


However, we can see where the problem comes from: there is no exact
representation of 1/3 in base ten. Similarly, there is no exact
representation in base two of numbers you're considering. For more
details, read Goldberg's aricle.


--
__Pascal Bourguignon__
http://www.informatimago.com
From: Aravindh Johendran on
On May 3, 4:42 am, Tamas K Papp <tkp...(a)gmail.com> wrote:


> Use rationals if you want these kind of calculations to be precise.
>
> The article by Goldberg [1] is a good intro to floating point
> arithmetic.  

Thanks for the pointers. Funny how numbers can be so complicated in
computers/programming.


-----------------------------

On May 3, 11:16 am, p...(a)informatimago.com (Pascal J. Bourguignon)
wrote:


> But understanding the problem is easy, it is taught to pupil at the
> end of primary school:

Ouch!

> However, we can see where the problem comes from: there is no exact
> representation of 1/3 in base ten. Similarly, there is no exact
> representation in base two of numbers you're considering. For more
> details, read Goldberg's aricle.

OK, am beginning to understand.
Thanks for the response and pointer.


- Aravindh

From: Barry Margolin on
In article
<0a14e585-ca3c-4838-832d-4fc2544daab4(a)i10g2000yqh.googlegroups.com>,
Aravindh Johendran <ajohendran(a)gmail.com> wrote:

> On May 3, 4:42�am, Tamas K Papp <tkp...(a)gmail.com> wrote:
>
>
> > Use rationals if you want these kind of calculations to be precise.
> >
> > The article by Goldberg [1] is a good intro to floating point
> > arithmetic. �
>
> Thanks for the pointers. Funny how numbers can be so complicated in
> computers/programming.

To quote Barbie: "Math is hard."

--
Barry Margolin, barmar(a)alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
*** PLEASE don't copy me on replies, I'll read them in the group ***