[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




Posted on the users mailing list.