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.
My Haskell solution (see http://bonsaicode.wordpress.com/2011/06/14/programming-praxis-big-numbers-input-and-output/ for a version with comments):