racket/format: change ~r to accept #:notation argument

Another possibility would be
  #:exponential? (or/c boolean? (-> rational? boolean?))
but that violates the "everything's a boolean" convention.
This commit is contained in:
Ryan Culpepper 2012-09-07 21:28:39 -04:00
parent 58b054c6a2
commit d70e80e837
3 changed files with 126 additions and 117 deletions

View File

@ -60,7 +60,8 @@
[~.s format/c]
[~.v format/c]
[~r (->* (rational?)
(#:exponential? any/c
(#:notation (or/c 'positional 'exponential
(-> rational? (or/c 'positional 'exponential)))
#:sign sign-mode/c
#:base base/c
#:precision precision/c
@ -177,29 +178,29 @@
#:sign [sign-mode #f]
#:base [base 10]
#:precision [precision 6]
#:exponential? [exponential? (not (or (zero? N)
(< (expt (extract base) (- (extract precision)))
(abs N)
(expt (extract base) (extract precision)))))]
#:notation [notation 'positional]
#:format-exponent [exp-format-exponent #f]
#:min-width [pad-digits-to 1]
#:pad-string [digits-padding " "])
(if exponential?
(catne N
#:who 'catn
#:sign sign-mode
#:base base
#:precision precision
#:format-exponent exp-format-exponent
#:pad-digits-to pad-digits-to
#:digits-padding digits-padding)
(catnp N
#:who 'catn
#:sign sign-mode
#:base base
#:precision precision
#:pad-digits-to pad-digits-to
#:digits-padding digits-padding)))
(let ([notation (if (procedure? notation) (notation N) notation)])
(case notation
((exponential)
(catne N
#:who 'catn
#:sign sign-mode
#:base base
#:precision precision
#:format-exponent exp-format-exponent
#:pad-digits-to pad-digits-to
#:digits-padding digits-padding))
((positional)
(catnp N
#:who 'catn
#:sign sign-mode
#:base base
#:precision precision
#:pad-digits-to pad-digits-to
#:digits-padding digits-padding)))))
(define (catnp N
#:who [who 'catnp]

View File

@ -12,7 +12,6 @@
(the-eval '(require racket/math racket/format)))
@title[#:tag "format"]{Converting Values to Strings}
@author[@author+email["Ryan Culpepper" "ryanc@racket-lang.org"]]
@note-lib[racket/format]
@ -47,7 +46,7 @@ at most @racket[max-width] characters.
(~a #\w "e" 'st)
(~a (list "red" 'green #"blue"))
(~a 17)
(~a #e1e20)
(eval:alts (~a @#,(racketvalfont "#e1e20")) (~a #e1e20))
(~a pi)
(~a (expt 6.1 87))
]
@ -189,17 +188,10 @@ marker is @racket["..."].
(or/c exact-nonnegative-integer?
(list/c '= exact-nonnegative-integer?))
3]
[#:exponential? exponential
any/c
(let ([num (lambda (n) (if (list? n) (cadr n) n))])
(not (or (zero? x)
(< (expt (num base) (- (num precision)))
(abs x)
(expt (num base) (num precision))))))]
[#:exp-precision exp-precision
(or/c exact-nonnegative-integer?
(list/c '= exact-nonnegative-integer?))
5]
[#:notation notation
(or/c 'positional 'exponential
(-> rational? (or/c 'positional 'exponential)))
'positional]
[#:format-exponent format-exponent
(or/c #f string? (-> exact-integer? string?))
#f]
@ -209,17 +201,35 @@ marker is @racket["..."].
Converts the rational number @racket[x] to a string in either
positional or exponential notation, depending on
@racket[exponential?]. The exactness or inexactness of @racket[x] does
not affect its formatting.
@racket[notation]. The exactness or inexactness of @racket[x] does not
affect its formatting.
The optional arguments control number formatting:
@itemize[
@item{@racket[precision] --- controls the number of digits after the decimal point
(or more accurately, the
@hyperlink["http://en.wikipedia.org/wiki/Radix_point"]{radix point}). When @racket[x]
is converted to exponential form, @racket[precision] applies only to the significand.
@item{@racket[notation] --- determines whether the number is printed
in positional or exponential notation. If @racket[notation] is a
function, it is applied to @racket[x] to get the notation to be used.
@interaction[#:eval the-eval
(~r 12345)
(~r 12345 #:notation 'exponential)
(let ([pick-notation
(lambda (x)
(if (or (< (abs x) 0.001) (> (abs x) 1000))
'exponential
'positional))])
(for/list ([i (in-range 1 5)])
(~r (expt 17 i) #:notation pick-notation)))
]
}
@item{@racket[precision] --- controls the number of digits after the
decimal point (or more accurately, the
@hyperlink["http://en.wikipedia.org/wiki/Radix_point"]{radix point}).
When @racket[x] is formatted in exponential form, @racket[precision]
applies to the significand.
If @racket[precision] is a natural number, then up to @racket[precision] digits are
displayed, but trailing zeroes are dropped, and if all digits after the decimal
@ -240,7 +250,7 @@ decimal point are used, and the decimal point is never dropped.
@item{@racket[min-width] --- if @racket[x] would normally be printed
with fewer than @racket[min-width] digits (including the decimal
point but not including the sign indicator), the output is left-padded
point but not including the sign indicator), the digits are left-padded
using @racket[pad-string].
@interaction[#:eval the-eval
@ -250,7 +260,8 @@ using @racket[pad-string].
(~r 1.5 #:min-width 4)
(~r 1.5 #:precision 4 #:min-width 10)
(~r 1.5 #:precision '(= 4) #:min-width 10)
(~r 1e10 #:min-width 6)
(eval:alts (~r @#,(racketvalfont "#e1e10") #:min-width 6)
(~r #e1e10 #:min-width 6))
]}
@item{@racket[pad-string] --- specifies the string used to pad the
@ -324,17 +335,18 @@ greater than @racket[10], then upper-case letters are used.
(~r 4.5 #:base 2)
(~r 3735928559 #:base 16)
(~r 3735928559 #:base '(up 16))
(~r 3735928559 #:base '(up 16) #:notation 'exponential)
]}
@item{@racket[format-exponent] --- determines how the exponent is displayed.
If @racket[format-exponent] is a string, the exponent is displayed with an
explicit sign (as with a @racket[sign-mode] of @racket['++]) and at least two
explicit sign (as with a @racket[sign] of @racket['++]) and at least two
digits, separated from the significand by the ``exponent marker''
@racket[format-exponent]:
@interaction[#:eval the-eval
(~r 1234 #:exponential? #t #:format-exponent "E")
(~r 1234 #:notation 'exponential #:format-exponent "E")
]
If @racket[format-exponent] is @racket[#f], the ``exponent marker'' is
@ -342,15 +354,15 @@ If @racket[format-exponent] is @racket[#f], the ``exponent marker'' is
@racket[base] otherwise:
@interaction[#:eval the-eval
(~r 1234 #:exponential? #t)
(~r 1234 #:exponential? #t #:base 8)
(~r 1234 #:notation 'exponential)
(~r 1234 #:notation 'exponential #:base 8)
]
If @racket[format-exponent] is a procedure, it is applied to the exponent and
the resulting string is appended to the significand:
@interaction[#:eval the-eval
(~r 1234 #:exponential? #t
(~r 1234 #:notation 'exponential
#:format-exponent (lambda (e) (format "E~a" e)))
]}

View File

@ -106,7 +106,7 @@
"3.141593")
(tc (~r pi #:precision 4)
"3.1416")
(tc (~r pi #:precision 0 #:exponential? #f)
(tc (~r pi #:precision 0)
"3")
(tc (~r 1.5 #:precision 4)
"1.5")
@ -116,7 +116,7 @@
"50")
(tc (~r 50 #:precision '(= 2))
"50.00")
(tc (~r 50 #:precision '(= 0) #:exponential? #f)
(tc (~r 50 #:precision '(= 0))
"50.")
(tc (~r 17)
@ -156,119 +156,115 @@
"202")
(tc (~r 4.5 #:base 2)
"100.1")
(tc (~r 3735928559 #:base 16 #:precision 10)
(tc (~r 3735928559 #:base 16)
"deadbeef")
(tc (~r 3735928559 #:base '(up 16) #:precision 10)
(tc (~r 3735928559 #:base '(up 16))
"DEADBEEF")
(tc (~r 999 #:precision 3)
"999")
(tc (~r 1000 #:precision 3)
"1e+03")
(tc (~r 0.9876 #:exponential? #t #:precision 3)
"9.876e-01")
"1000")
(tc (~r 100 #:base 2 #:precision 3)
"1.101×2^+06")
;; ~r #:notation 'positional
(tc (~r 1234 #:precision 3 #:format-exponent "E")
"1.234E+03")
(tc (~r 12345 #:precision 3)
"1.235e+04")
(tc (~r 12345 #:precision 2)
"1.23e+04")
(tc (~r 10000 #:precision 2)
"1e+04")
(tc (~r 10000 #:precision '(= 2))
"1.00e+04")
(tc (~r 12345 #:precision 4
#:min-width 12)
" 1.2345e+04")
;; ~r #:exponential? #f
(tc (~r #:exponential? #f pi)
(tc (~r #:notation 'positional pi)
"3.141593")
(tc (~r #:exponential? #f pi #:precision 4)
(tc (~r #:notation 'positional pi #:precision 4)
"3.1416")
(tc (~r #:exponential? #f pi #:precision 0)
(tc (~r #:notation 'positional pi #:precision 0)
"3")
(tc (~r #:exponential? #f 1.5 #:precision 4)
(tc (~r #:notation 'positional 1.5 #:precision 4)
"1.5")
(tc (~r #:exponential? #f 1.5 #:precision '(= 4))
(tc (~r #:notation 'positional 1.5 #:precision '(= 4))
"1.5000")
(tc (~r #:exponential? #f 50 #:precision 2)
(tc (~r #:notation 'positional 50 #:precision 2)
"50")
(tc (~r #:exponential? #f 50 #:precision '(= 2))
(tc (~r #:notation 'positional 50 #:precision '(= 2))
"50.00")
(tc (~r #:exponential? #f 50 #:precision '(= 0))
(tc (~r #:notation 'positional 50 #:precision '(= 0))
"50.")
(tc (~r #:exponential? #f 17)
(tc (~r #:notation 'positional 17)
"17")
(tc (~r #:exponential? #f 17 #:min-width 4)
(tc (~r #:notation 'positional 17 #:min-width 4)
" 17")
(tc (~r #:exponential? #f -42 #:min-width 4)
(tc (~r #:notation 'positional -42 #:min-width 4)
"- 42")
(tc (~r #:exponential? #f 1.5 #:min-width 4)
(tc (~r #:notation 'positional 1.5 #:min-width 4)
" 1.5")
(tc (~r #:exponential? #f 1.5 #:precision 4 #:min-width 10)
(tc (~r #:notation 'positional 1.5 #:precision 4 #:min-width 10)
" 1.5")
(tc (~r #:exponential? #f 1.5 #:precision '(= 4) #:min-width 10)
(tc (~r #:notation 'positional 1.5 #:precision '(= 4) #:min-width 10)
" 1.5000")
(tc (~r #:exponential? #f -42 #:min-width 4 #:pad-string "0")
(tc (~r #:notation 'positional -42 #:min-width 4 #:pad-string "0")
"-0042")
(tc (~r #:exponential? #f 17 #:min-width 4 #:pad-string "0")
(tc (~r #:notation 'positional 17 #:min-width 4 #:pad-string "0")
"0017")
(tc (~r #:exponential? #f -42 #:min-width 4 #:pad-string "0")
(tc (~r #:notation 'positional -42 #:min-width 4 #:pad-string "0")
"-0042")
(tc (for/list ([x '(17 0 -42)]) (~r #:exponential? #f x))
(tc (for/list ([x '(17 0 -42)]) (~r #:notation 'positional x))
'("17" "0" "-42"))
(tc (for/list ([x '(17 0 -42)]) (~r #:exponential? #f x #:sign '+))
(tc (for/list ([x '(17 0 -42)]) (~r #:notation 'positional x #:sign '+))
'("+17" "0" "-42"))
(tc (for/list ([x '(17 0 -42)]) (~r #:exponential? #f x #:sign '++))
(tc (for/list ([x '(17 0 -42)]) (~r #:notation 'positional x #:sign '++))
'("+17" "+0" "-42"))
(tc (for/list ([x '(17 0 -42)]) (~r #:exponential? #f x #:sign 'parens))
(tc (for/list ([x '(17 0 -42)]) (~r #:notation 'positional x #:sign 'parens))
'("17" "0" "(42)"))
(tc (let ([sign-table '(("" " up") "an even " ("" " down"))])
(for/list ([x '(17 0 -42)]) (~r #:exponential? #f x #:sign sign-table)))
(for/list ([x '(17 0 -42)]) (~r #:notation 'positional x #:sign sign-table)))
'("17 up" "an even 0" "42 down"))
(tc (~r #:exponential? #f 100 #:base 7)
(tc (~r #:notation 'positional 100 #:base 7)
"202")
(tc (~r #:exponential? #f 4.5 #:base 2)
(tc (~r #:notation 'positional 4.5 #:base 2)
"100.1")
(tc (~r #:exponential? #f 3735928559 #:base 16)
(tc (~r #:notation 'positional 3735928559 #:base 16)
"deadbeef")
(tc (~r #:exponential? #f 3735928559 #:base '(up 16))
(tc (~r #:notation 'positional 3735928559 #:base '(up 16))
"DEADBEEF")
;; ~r #:exponential? #t
;; ~r #:notation 'exponential
(tc (~r #:exponential? #t 1000)
"1e+03")
(tc (~r #:exponential? #t 0.9876)
"9.876e-01")
(tc (~r #:exponential? #t 100 #:base 2)
"1.1001×2^+06")
(tc (~r #:exponential? #t 1234 #:format-exponent "E")
"1.234E+03")
(tc (~r #:exponential? #t 12345 #:precision 3)
(tc (~r 12345 #:precision 3 #:notation 'exponential)
"1.235e+04")
(tc (~r #:exponential? #t 12345 #:precision 2)
(tc (~r 12345 #:precision 2 #:notation 'exponential)
"1.23e+04")
(tc (~r #:exponential? #t 10000 #:precision 2)
(tc (~r 10000 #:precision 2 #:notation 'exponential)
"1e+04")
(tc (~r #:exponential? #t 10000 #:precision '(= 2))
(tc (~r 10000 #:precision '(= 2) #:notation 'exponential)
"1.00e+04")
(tc (~r #:exponential? #t 12345 #:min-width 12)
(tc (~r 12345 #:precision 4 #:min-width 12 #:notation 'exponential)
" 1.2345e+04")
(tc (~r #:notation 'exponential 1000)
"1e+03")
(tc (~r #:notation 'exponential 0.9876)
"9.876e-01")
(tc (~r #:notation 'exponential 100 #:base 2)
"1.1001×2^+06")
(tc (~r #:notation 'exponential 1234 #:format-exponent "E")
"1.234E+03")
(tc (~r #:notation 'exponential 12345 #:precision 3)
;; note rounding!
"1.235e+04")
(tc (~r #:notation 'exponential 12345 #:precision 2)
"1.23e+04")
(tc (~r #:notation 'exponential 10000 #:precision 2)
"1e+04")
(tc (~r #:notation 'exponential 10000 #:precision '(= 2))
"1.00e+04")
(tc (~r #:notation 'exponential 12345 #:min-width 12)
" 1.2345e+04")
(tc (~r 3735928559 #:base '(up 16) #:precision 6 #:notation 'exponential)
;; note rounding!
"D.EADBEF×16^+07")