This is the mail archive of the guile@cygnus.com mailing list for the guile project.
Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
---|---|---|
Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |
hjstein@bfr.co.il (Harvey J. Stein) writes: > Jim Blandy <jimb@red-bean.com> writes: > > Ahh, this is subtle. The result fits in a double, but neither of the > > operands does, so you can't convert to a double and then do the > > division. This behavior is unfortunate. > > Exactly. You have to be serious about doing your computations on > bignums. > > > I think Guile's behavior is legal, though. The "encouraged, but not > > required" clause applies only to the rest of the sentence. Since > > Guile does not support exact rationals, it silently coerces its result > > to an inexact number. +#.# is an inexact positive infinity. R5RS > > doesn't specify the precision with which the result is computed, only > > the precision with which it is represented. > > Correct, but that sentence is about bignums & rationals. It's the > next sentence that's at issue: Actually, it's not conformant even in this sense: guile> (define a (/ 1 0)) guile> a +#.# guile> (inexact? a) #f guile> (inexact->exact a) ERROR: In procedure inexact->exact in expression (inexact->exact a): ERROR: Wrong type argument in position 1: +#.# ABORT: (wrong-type-arg) Type "(backtrace)" to get more information. +#.# isn't inexact, so / isn't actually coercing to inexact when necessary, it's returning another type of object. Here's the kind of thing I was thinking of. This is just off the top of my head, so there are probably much better ways of doing these things that maybe a numerical analyst on this list could suggest, but here's a start: (define (bb->i-quotient n d) ;;; Bignum bignum quotient whose result is inexact, assuming it fits ;;; in an exact. ;;; n/d = (quotient n d) + (/ (remainder n d) d) ;;; = (quotient n d) + (/ (* 2 (remainder n d)) d 2) ;;; = (quotient n d) + .5*(/ (* 2 (remainder n d)) d) (define (eiq n d iters) (if (= iters 0) 0 (+ (quotient n d) (* .5 (eiq (* 2 (remainder n d)) d (- iters 1)))))) (eiq n d 60)) (define (dumb-rationalize n) ;;; Convert the inexact n to a pair (numerator . denomenator) of ;;; exacts such that (/ numerator denomenator) = n (let* ((integer-part (inexact->exact (floor n))) (fractional-part (- n integer-part))) (let loop ((num 0) (denom 1)) (let ((q (bb->i-quotient num denom))) (cond ((= fractional-part q) (cons (+ (* denom integer-part) num) denom)) (else (if (<= (bb->i-quotient (+ (* 2 num) 1) (* 2 denom)) fractional-part) (loop (+ (* 2 num) 1) (* 2 denom)) (loop (* 2 num) (* 2 denom))))))))) (define (bi->i-quotient n d) ;;; Bignum inexact quotient whose result is inexact, assuming it fits ;;; in an inexact. (let ((r (dumb-rationalize d))) (bb->i-quotient (* n (cdr r)) (car r)))) (define (bi->i-product big inexact) ;;; Bignum inexact product whose result is inexact, assuming it fits ;;; in an inexact. (let ((r (dumb-rationalize inexact))) (bb->i-quotient (* big (car r)) (cdr r)))) -- Harvey J. Stein BFM Financial Research hjstein@bfr.co.il