123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111 |
- ; Part of Scheme 48 1.9. See file COPYING for notices and license.
- ; Authors: Richard Kelsey, Jonathan Rees, Mike Sperber
- ; Inexact numbers as mere shells surrounding exact numbers.
- (define-extended-number-type <innum> (<inexact>)
- (make-innum exact)
- innum?
- (exact innum-exact))
- (define-method &exact? ((n <innum>)) #f)
- (define-method &complex? ((n <innum>)) (complex? (innum-exact n)))
- (define-method &real? ((n <innum>)) (real? (innum-exact n)))
- (define-method &rational? ((n <innum>)) (rational? (innum-exact n)))
- (define-method &integer? ((n <innum>)) (integer? (innum-exact n)))
- (define-method &exact->inexact ((n <number>))
- (if (innum? n)
- (next-method)
- (make-innum n)))
- (define-method &inexact->exact ((n <innum>)) (innum-exact n))
- (define (inexactify n)
- (if (exact? n)
- (exact->inexact n)
- n))
- (define (define-innum-method mtable proc)
- (define-method mtable ((m <innum>) (n <number>))
- (inexactify (proc (innum-exact m) n)))
- (define-method mtable ((m <number>) (n <innum>))
- (inexactify (proc m (innum-exact n)))))
- (define-innum-method &+ +)
- (define-innum-method &- -)
- (define-innum-method &* *)
- (define-innum-method &/ /)
- (define-innum-method "ient quotient)
- (define-innum-method &remainder remainder)
- (define (define-innum-comparison mtable proc)
- (define-method mtable ((m <innum>) (n <number>))
- (proc (innum-exact m) n))
- (define-method mtable ((m <number>) (n <innum>))
- (proc m (innum-exact n))))
- (define-innum-comparison &= =)
- (define-innum-comparison &< <)
- (define-method &numerator ((n <innum>))
- (inexactify (numerator (innum-exact n))))
- (define-method &denominator ((n <innum>))
- (inexactify (denominator (innum-exact n))))
- (define-method &floor ((n <innum>))
- (inexactify (floor (innum-exact n))))
- (define-method &number->string ((i <innum>) radix)
- (let ((n (innum-exact i)))
- (cond ((integer? n)
- (string-append (number->string n radix) "."))
- ((rational? n)
- (let ((q (denominator n)))
- (if (= radix 10)
- (let ((foo (decimable? q)))
- (if foo
- (decimal-representation (numerator n) q foo)
- (string-append "#i" (number->string n radix))))
- (string-append "#i" (number->string n radix)))))
- (else
- (string-append "#i" (number->string n radix))))))
- ; The Scheme report obligates us to print inexact rationals using
- ; decimal points whenever this can be done without losing precision.
- (define (decimal-representation p q foo)
- (let ((kludge (number->string (* (car foo) (abs (remainder p q)))
- 10)))
- (string-append (if (< p 0) "-" "")
- (number->string (quotient (abs p) q) 10)
- "."
- (string-append (do ((i (- (cdr foo) (string-length kludge))
- (- i 1))
- (l '() (cons #\0 l)))
- ((<= i 0) (list->string l)))
- kludge))))
- (define (ratio-string p q radix)
- (string-append (number->string p radix)
- "/"
- (number->string q radix)))
- ; (decimable? n) => non-#f iff n is a product of 2's and 5's.
- ; The value returned is (k . i) such that 10^i divides n * k.
- (define (decimable? n)
- (let loop ((n n) (d 1) (i 0))
- (if (= n 1)
- (cons d i)
- (let ((q (quotient n 10))
- (r (remainder n 10)))
- (cond ((= r 0) (loop q d (+ i 1)))
- ((= r 5) (loop (quotient n 5) (* d 2) (+ i 1)))
- ((even? r) (loop (quotient n 2) (* d 5) (+ i 1)))
- (else #f))))))
|