I’m Embarrassed!
October 4, 2016
The bug is easy enough to fix. Multiply the input number by 100, round, then use quotient
and modulo
to split the dollars and cents; the formatting is unchanged from the previous solution:
(define (dollar x) (define (commas n) (let ((xs (reverse (map number->string (digits n))))) (let loop ((xs (drop 3 xs)) (zs (reverse (take 3 xs)))) (if (null? xs) (apply string-append zs) (loop (drop 3 xs) (append (reverse (take 3 xs)) (list ",") zs)))))) (define (zero n) (if (zero? n) "00" (if (< n 10) (string-append "0" (number->string n)) (number->string n)))) (let* ((n (inexact->exact (round (* x 100)))) (dollars (quotient n 100)) (cents (modulo n 100))) (string-append "$" (commas dollars) "." (zero cents))))
This correctly solves Matthew’s bug report:
> (dollar 1234567.9999) $1,234,568.00
You can run the program at http://ideone.com/xg7nFo.
Updated my python solution so it rounds instead of truncating.
Sorry about that. I find it’s easy to get these simple problems wrong, just by not paying enough attention. New solution looks good anyway.