[plt-scheme] Numerical precision
From: Jaime Vargas (jev at mac.com)
Date: Wed Mar 11 16:23:45 EDT 2009 |
|
On Mar 11, 2009, at 3:29 PM, Joe Marshall wrote:
>> (define numerical-precision (make-parameter 2))
>
> This is a little odd. Do you expect to dynamically change the
> precision?
> If not, then you might want to make this a regular define rather than
> a parameter. If so, however, you'll have to be very careful when you
> change the precision.
Not within a given simulation. However, I would like to be able to
specify the
precision. A normal define will not allow changes, because it becomes
immutable
when imported by other modules. And enclosing all the computation within
a parameterize form makes very obvious the precision being used.
>> (define (N)
>> (expt 10 (numerical-precision)))
>
> This is a procedure that raises 10 to the precision power every time
> it is called. If the precision doesn't change, you don't need to do
> this
> every time.
>
>> (define (1/N)
>> (/ 1 (N)))
>
> Likewise, this computes the reciprocal every time it is called.
>
>> (define (round:N x)
>> (* (1/N) (round (* x (N)))))
>
> And here you will notice that when you round, you will raise 10 to the
> correct power twice and take its reciprocal once.
Agreed. I would like to have this computations to happen only once. But
reactive to changes in the numerical-precision parameter.
>> (define (*:N . nums)
>> (round:N (apply * nums)))
>>
>> (define (/:N . nums)
>> (round:N (apply / nums)))
>>
>> (define (+:N . nums)
>> (round:N (apply + nums)))
>>
>> (define (-:N . nums)
>> (round:N (apply - nums)))
>
> You have defined something weird here. Your arithmetic is no
> longer associative where you might expect it to be.
How so, I don't see the problem. Again, some naive testing.
#lang scheme
(require "accountants-math.ss")
(equal? (* 1/2 (+ 2/3 1/3))
(+ (* 1/2 1/3) (* 1/2 2/3)))
=> #t
(equal? (/ (+ 2/3 1/3) 1/2)
(+ (/ 2/3 1/2) (/ 1/3 1/2)))
=> #t
(equal? (* 1/2 (- 2/3 1/3))
(- (* 1/2 2/3) (* 1/2 1/3)))
=> #t
(equal? (/ (- 2/3 1/3) 1/2)
(- (/ 2/3 1/2) (/ 1/3 1/2)))
=> #t
-- Jaime