Big Numbers: Input And Output

June 14, 2011

These functions are straight forward, and assume that the radix is less than or equal to big-base:

(define (string->big str . args)
  (define (char->digit c)
    (cond ((char-numeric? c) (- (char->integer c) 48))
          ((char-upper-case? c) (- (char->integer c) 55))
          ((char-lower-case? c) (- (char->integer c) 87))
          (else (error 'char->digit "illegal character"))))
  (if (string=? str "") '(0)
    (let* ((radix (list 1 (if (null? args) 10 (car args))))
           (s (if (char=? (string-ref str 0) #\-) -1 1))
           (ds (string->list str))
           (ds (if (positive? s) ds (cdr ds)))
           (ds (map char->digit ds)))
      (let loop ((ds (cdr ds)) (big (list 1 (car ds))))
        (if (null? ds) (cons (* s (car big)) (cdr big))
          (loop (cdr ds)
                (big-plus (big-times big radix)
                          (list 1 (car ds)))))))))

(define (big->string big . args)
  (define (digit->char d)
    (cond ((< d 10) (integer->char (+ d 48)))
          ((< d 36) (integer->char (+ d 55)))
          (else (error 'digit->char "illegal digit"))))
  (if (big-zero? big) "0"
    (if (big-negative? big) (string-append "-" (big->string (big-negate big)))
      (let ((radix (list 1 (if (null? args) 10 (car args)))))
        (let loop ((big big) (ds '()))
          (if (big-zero? big) (list->string ds)
            (call-with-values
              (lambda () (big-divide big radix))
              (lambda (q r) (loop q (cons (digit->char (cadr r)) ds))))))))))

Testing these functions turned up a big in big-divide: when the quotient was zero, it was represented as (1 0) instead of the correct representation (0).

The complete big-number library to this point is shown on the next page. You can run the program at http://programmingpraxis.codepad.org/4TvtUDo3.

Advertisement

Pages: 1 2 3

One Response to “Big Numbers: Input And Output”

  1. My Haskell solution (see http://bonsaicode.wordpress.com/2011/06/14/programming-praxis-big-numbers-input-and-output/ for a version with comments):

    readBase :: (Num a, Enum a) => a -> String -> a
    readBase b ('-':xs) = - readBase b xs
    readBase b xs       = foldl (\a x -> b * a + val x) 0 xs where
        val d = maybe (error "unrecognized digit") id . lookup d $ zip
                (['0'..'9'] ++ ['A'..'Z'] ++ ['a'..'z']) [0..]
    
    showBase :: Integral a => a -> a -> String
    showBase b n = if n < 0 then '-' : showBase b (abs n) else
                   map (digit . snd) $ m : reverse ms  where
        ((_:ms), (m:_)) = span ((> 0) . fst) $ iterate (flip divMod b . fst) (n, 0)
        digit d = maybe undefined id . lookup d . zip [0..] $
                  ['0'..'9'] ++ ['A'..'Z'] ++ ['a'..'z']
    

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: