[plt-scheme] order of magnitude

From: Jos Koot (jos.koot at telefonica.net)
Date: Thu Nov 5 06:04:22 EST 2009

Some browsing did not lead me to finding a function that accepts an exact positive rational number and returns its order of magnitude (an exact integer number) Something like:

(define log10 (inexact->exact (log 10)))
(define (order-of-magnitude q) (floor (/ (inexact->exact (log q)) log10)))

However, due to inexactness of function log we find:

(/ (inexact->exact (log #e1000e1000000)) log10) --> close to but sligtly less than 1000003

and hence:

(order-of-magnitude #e1000e1000000) ; --> 1000002 

The wanted answer is 1000003. So I did the following:

(define order-of-magnitude
 (let*
  ((log10 (inexact->exact (log 10)))
   (10log (λ (q) (/ (inexact->exact (log q)) log10))))
  (λ (q)
   (unless (and (rational? q) (exact? q) (positive? q))
    (raise-type-error 'magnitude "positive exact rational number" q))
   (let* ((m (floor (10log q))) (k (expt 10 m)))
    ; From now on all arithmetic operations and their operands are exact.
    (let loop ((m m) (lower (* k 1/10)) (middle k) (upper (* k 10)))
     (cond
      ((<= q lower) (loop (sub1 m) (* lower 1/10) lower middle))
      ((>= q upper) (loop (add1 m) middle upper (* upper 10)))
      (else m)))))))

(order-of-magnitude #e1000e1000000) ; --> 1000003

However, this seems rather complicated. Does someone have or know of a simpler and faster function for this purpose?

Thanks, Jos
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.racket-lang.org/users/archive/attachments/20091105/628a6920/attachment.html>

Posted on the users mailing list.