; formatted numeric output
(define (digits n . args)
(let ((b (if (null? args) 10 (car args))))
(let loop ((n n) (d '()))
(if (zero? n) d
(loop (quotient n b)
(cons (modulo n b) d))))))
(define (digit->char d) (integer->char (+ d 48)))
(define (rept n . cs)
(make-string n (if (pair? cs) (car cs) #\space)))
(define (align str wid aline)
(let ((len (string-length str)))
(cond ((< wid len) (rept wid #\#))
((eq? aline'left) (string-append str (rept (- wid len))))
((eq? aline 'center)
(let* ((left (quotient (- wid len) 2)) (right (- wid len left)))
(string-append (rept left) str (rept right))))
((eq? aline 'right) (string-append (rept (- wid len)) str))
(else (error 'align "invalid alignment specifier")))))
(define (number->decimal num wid . aline)
(if (not (integer? num))
(error 'number->decimal "invalid input")
(let ((aline (if (pair? aline) (car aline) 'right))
(sign (if (negative? num) "-" (if (zero? num) "0" "")))
(num (list->string (map digit->char (digits (abs num))))))
(align (string-append sign num) wid aline))))
(define (number->float num wid prec . aline)
(if (not (number? num))
(error 'number->float "invalid input")
(let* ((aline (if (pair? aline) (car aline) 'right))
(sign (if (negative? num) "-" (if (zero? num) "0" "")))
(num (abs num))
(left (inexact->exact (truncate num)))
(right (inexact->exact (round (* (- num left) (expt 10 prec)))))
(left (list->string (map digit->char (digits left))))
(right (if (zero? right) (rept prec #\0)
(list->string (map digit->char (digits right))))))
(align (string-append sign left "." right) wid aline))))
(display "|") (display (number->decimal 1234 12 'left)) (display "|") (newline)
(display "|") (display (number->decimal -1234 12 'right)) (display "|") (newline)
(display "|") (display (number->decimal 0 12 'center)) (display "|") (newline)
(display "|") (display (number->float 1234.56 12 4 'left)) (display "|") (newline)
(display "|") (display (number->float -1234.5678 12 2 'right)) (display "|") (newline)
(display "|") (display (number->float 1234 12 2 'center)) (display "|") (newline)
(display "|") (display (number->float 1234.56 12 4)) (display "|") (newline)
(display "|") (display (number->float 0.1234 12 4)) (display "|") (newline)
(display "|") (display (number->float 0 12 4)) (display "|") (newline)