innum.scm 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. ; Part of Scheme 48 1.9. See file COPYING for notices and license.
  2. ; Authors: Richard Kelsey, Jonathan Rees, Mike Sperber
  3. ; Inexact numbers as mere shells surrounding exact numbers.
  4. (define-extended-number-type <innum> (<inexact>)
  5. (make-innum exact)
  6. innum?
  7. (exact innum-exact))
  8. (define-method &exact? ((n <innum>)) #f)
  9. (define-method &complex? ((n <innum>)) (complex? (innum-exact n)))
  10. (define-method &real? ((n <innum>)) (real? (innum-exact n)))
  11. (define-method &rational? ((n <innum>)) (rational? (innum-exact n)))
  12. (define-method &integer? ((n <innum>)) (integer? (innum-exact n)))
  13. (define-method &exact->inexact ((n <number>))
  14. (if (innum? n)
  15. (next-method)
  16. (make-innum n)))
  17. (define-method &inexact->exact ((n <innum>)) (innum-exact n))
  18. (define (inexactify n)
  19. (if (exact? n)
  20. (exact->inexact n)
  21. n))
  22. (define (define-innum-method mtable proc)
  23. (define-method mtable ((m <innum>) (n <number>))
  24. (inexactify (proc (innum-exact m) n)))
  25. (define-method mtable ((m <number>) (n <innum>))
  26. (inexactify (proc m (innum-exact n)))))
  27. (define-innum-method &+ +)
  28. (define-innum-method &- -)
  29. (define-innum-method &* *)
  30. (define-innum-method &/ /)
  31. (define-innum-method &quotient quotient)
  32. (define-innum-method &remainder remainder)
  33. (define (define-innum-comparison mtable proc)
  34. (define-method mtable ((m <innum>) (n <number>))
  35. (proc (innum-exact m) n))
  36. (define-method mtable ((m <number>) (n <innum>))
  37. (proc m (innum-exact n))))
  38. (define-innum-comparison &= =)
  39. (define-innum-comparison &< <)
  40. (define-method &numerator ((n <innum>))
  41. (inexactify (numerator (innum-exact n))))
  42. (define-method &denominator ((n <innum>))
  43. (inexactify (denominator (innum-exact n))))
  44. (define-method &floor ((n <innum>))
  45. (inexactify (floor (innum-exact n))))
  46. (define-method &number->string ((i <innum>) radix)
  47. (let ((n (innum-exact i)))
  48. (cond ((integer? n)
  49. (string-append (number->string n radix) "."))
  50. ((rational? n)
  51. (let ((q (denominator n)))
  52. (if (= radix 10)
  53. (let ((foo (decimable? q)))
  54. (if foo
  55. (decimal-representation (numerator n) q foo)
  56. (string-append "#i" (number->string n radix))))
  57. (string-append "#i" (number->string n radix)))))
  58. (else
  59. (string-append "#i" (number->string n radix))))))
  60. ; The Scheme report obligates us to print inexact rationals using
  61. ; decimal points whenever this can be done without losing precision.
  62. (define (decimal-representation p q foo)
  63. (let ((kludge (number->string (* (car foo) (abs (remainder p q)))
  64. 10)))
  65. (string-append (if (< p 0) "-" "")
  66. (number->string (quotient (abs p) q) 10)
  67. "."
  68. (string-append (do ((i (- (cdr foo) (string-length kludge))
  69. (- i 1))
  70. (l '() (cons #\0 l)))
  71. ((<= i 0) (list->string l)))
  72. kludge))))
  73. (define (ratio-string p q radix)
  74. (string-append (number->string p radix)
  75. "/"
  76. (number->string q radix)))
  77. ; (decimable? n) => non-#f iff n is a product of 2's and 5's.
  78. ; The value returned is (k . i) such that 10^i divides n * k.
  79. (define (decimable? n)
  80. (let loop ((n n) (d 1) (i 0))
  81. (if (= n 1)
  82. (cons d i)
  83. (let ((q (quotient n 10))
  84. (r (remainder n 10)))
  85. (cond ((= r 0) (loop q d (+ i 1)))
  86. ((= r 5) (loop (quotient n 5) (* d 2) (+ i 1)))
  87. ((even? r) (loop (quotient n 2) (* d 5) (+ i 1)))
  88. (else #f))))))