From 6b2bcdd022fc13faaab7d75223bbd5a4082db7de Mon Sep 17 00:00:00 2001 From: Andy Fingerhut Date: Tue, 27 Mar 2012 08:56:23 -0700 Subject: [PATCH 12/12] Fixes for CLJ-768 and other problems found with cl-format ~f directive Without the changes to cl_format.clj, 46 of the 72 new unit tests added to test_cl_format.clj fail. --- src/clj/clojure/pprint/cl_format.clj | 41 ++++++++--- .../clojure/test_clojure/pprint/test_cl_format.clj | 72 ++++++++++++++++++++ 2 files changed, 105 insertions(+), 8 deletions(-) diff --git a/src/clj/clojure/pprint/cl_format.clj b/src/clj/clojure/pprint/cl_format.clj index 74cd33b..246b65d 100644 --- a/src/clj/clojure/pprint/cl_format.clj +++ b/src/clj/clojure/pprint/cl_format.clj @@ -583,11 +583,24 @@ string, or one character longer." (defn- round-str [m e d w] (if (or d w) (let [len (count m) - round-pos (if d (+ e d 1)) - round-pos (if (and w (< (inc e) (dec w)) - (or (nil? round-pos) (< (dec w) round-pos))) - (dec w) - round-pos) + ;; Every formatted floating point number should include at + ;; least one decimal digit and a decimal point. + w (if w (max 2 w)) + round-pos (cond + ;; If d was given, that forces the rounding + ;; position, regardless of any width that may + ;; have been specified. + d (+ e d 1) + ;; Otherwise w was specified, so pick round-pos + ;; based upon that. + ;; If e>=0, then abs value of number is >= 1.0, + ;; and e+1 is number of decimal digits before the + ;; decimal point when the number is written + ;; without scientific notation. Never round the + ;; number before the decimal point. + (>= e 0) (max (inc e) (dec w)) + ;; e < 0, so number abs value < 1.0 + :else (+ w e)) [m1 e1 round-pos len] (if (= round-pos 0) [(str "0" m) (inc e) 1 (inc len)] [m e round-pos len])] @@ -600,16 +613,21 @@ string, or one character longer." (if (>= (int round-char) (int \5)) (let [round-up-result (inc-s result) expanded (> (count round-up-result) (count result))] - [round-up-result e1 expanded]) + [(if expanded + (subs round-up-result 0 (dec (count round-up-result))) + round-up-result) + e1 expanded]) [result e1 false])) [m e false])) [m e false])) [m e false])) (defn- expand-fixed [m e d] - (let [m1 (if (neg? e) (str (apply str (repeat (dec (- e)) \0)) m) m) + (let [[m1 e1] (if (neg? e) + [(str (apply str (repeat (dec (- e)) \0)) m) -1] + [m e]) len (count m1) - target-len (if d (+ e d 1) (inc e))] + target-len (if d (+ e1 d 1) (inc e1))] (if (< len target-len) (str m1 (apply str (repeat (- target-len len) \0))) m1))) @@ -646,6 +664,13 @@ string, or one character longer." [rounded-mantissa scaled-exp expanded] (round-str mantissa scaled-exp d (if w (- w (if add-sign 1 0)))) fixed-repr (get-fixed rounded-mantissa (if expanded (inc scaled-exp) scaled-exp) d) + fixed-repr (if (and w d + (>= d 1) + (= (.charAt fixed-repr 0) \0) + (= (.charAt fixed-repr 1) \.) + (> (count fixed-repr) (- w (if add-sign 1 0)))) + (subs fixed-repr 1) ; chop off leading 0 + fixed-repr) prepend-zero (= (first fixed-repr) \.)] (if w (let [len (count fixed-repr) diff --git a/test/clojure/test_clojure/pprint/test_cl_format.clj b/test/clojure/test_clojure/pprint/test_cl_format.clj index 62fa685..b754cb0 100644 --- a/test/clojure/test_clojure/pprint/test_cl_format.clj +++ b/test/clojure/test_clojure/pprint/test_cl_format.clj @@ -205,11 +205,83 @@ (cl-format nil "~,1f" 0.99) "1.0" (cl-format nil "~,2f" 0.99) "0.99" (cl-format nil "~,3f" 0.99) "0.990" + (cl-format nil "~,3f" -0.099) "-0.099" + (cl-format nil "~,4f" -0.099) "-0.0990" + (cl-format nil "~,5f" -0.099) "-0.09900" + (cl-format nil "~,3f" 0.099) "0.099" + (cl-format nil "~,4f" 0.099) "0.0990" + (cl-format nil "~,5f" 0.099) "0.09900" (cl-format nil "~f" -1) "-1.0" (cl-format nil "~2f" -1) "-1." (cl-format nil "~3f" -1) "-1." (cl-format nil "~4f" -1) "-1.0" (cl-format nil "~8f" -1) " -1.0" + (cl-format nil "~2f" -0.0099) "-0." + (cl-format nil "~3f" -0.0099) "-0." + (cl-format nil "~4f" -0.0099) "-.01" + (cl-format nil "~5f" -0.0099) "-0.01" + (cl-format nil "~6f" -0.0099) "-.0099" + (cl-format nil "~1f" 0.0099) "0." + (cl-format nil "~2f" 0.0099) "0." + (cl-format nil "~3f" 0.0099) ".01" + (cl-format nil "~4f" 0.0099) "0.01" + (cl-format nil "~5f" 0.0099) ".0099" + (cl-format nil "~6f" 0.0099) "0.0099" + (cl-format nil "~1f" -0.099) "-.1" + (cl-format nil "~2f" -0.099) "-.1" + (cl-format nil "~3f" -0.099) "-.1" + (cl-format nil "~4f" -0.099) "-0.1" + (cl-format nil "~5f" -0.099) "-.099" + (cl-format nil "~6f" -0.099) "-0.099" + (cl-format nil "~1f" 0.099) ".1" + (cl-format nil "~2f" 0.099) ".1" + (cl-format nil "~3f" 0.099) "0.1" + (cl-format nil "~4f" 0.099) ".099" + (cl-format nil "~5f" 0.099) "0.099" + (cl-format nil "~1f" -0.99) "-1." + (cl-format nil "~2f" -0.99) "-1." + (cl-format nil "~3f" -0.99) "-1." + (cl-format nil "~4f" -0.99) "-.99" + (cl-format nil "~5f" -0.99) "-0.99" + (cl-format nil "~1f" 0.99) "1." + (cl-format nil "~2f" 0.99) "1." + (cl-format nil "~3f" 0.99) ".99" + (cl-format nil "~4f" 0.99) "0.99" + (cl-format nil "~1f" 111.11111) "111." + (cl-format nil "~4f" 111.11111) "111." + (cl-format nil "~5f" 111.11111) "111.1" + (cl-format nil "~1f" -111.11111) "-111." + (cl-format nil "~5f" -111.11111) "-111." + (cl-format nil "~6f" -111.11111) "-111.1" + (cl-format nil "~1f" 555.55555) "556." + (cl-format nil "~4f" 555.55555) "556." + (cl-format nil "~5f" 555.55555) "555.6" + (cl-format nil "~8f" 555.55555) "555.5556" + (cl-format nil "~1f" -555.55555) "-556." + (cl-format nil "~5f" -555.55555) "-556." + (cl-format nil "~6f" -555.55555) "-555.6" + (cl-format nil "~8f" -555.55555) "-555.556" + (cl-format nil "~1f" 999.999) "1000." + (cl-format nil "~5f" 999.999) "1000." + (cl-format nil "~6f" 999.999) "1000.0" + (cl-format nil "~7f" 999.999) "999.999" + (cl-format nil "~8f" 999.999) " 999.999" + (cl-format nil "~1f" -999.999) "-1000." + (cl-format nil "~6f" -999.999) "-1000." + (cl-format nil "~7f" -999.999) "-1000.0" + (cl-format nil "~8f" -999.999) "-999.999" + (cl-format nil "~5,2f" 111.11111) "111.11" + (cl-format nil "~3,1f" -0.0099) "-.0" + (cl-format nil "~6,4f" -0.0099) "-.0099" + (cl-format nil "~6,5f" -0.0099) "-.00990" + (cl-format nil "~6,6f" -0.0099) "-.009900" + (cl-format nil "~6,4f" 0.0099) "0.0099" + (cl-format nil "~6,5f" 0.0099) ".00990" + (cl-format nil "~6,6f" 0.0099) ".009900" + (cl-format nil "~2,1f" 0.0099) ".0" + (cl-format nil "~6,2f" -111.11111) "-111.11" + (cl-format nil "~6,3f" -111.11111) "-111.111" + (cl-format nil "~8,5f" -111.11111) "-111.11111" (cl-format nil "~12,10f" 1.23456789014) "1.2345678901" (cl-format nil "~12,10f" 1.23456789016) "1.2345678902" (cl-format nil "~13,10f" -1.23456789014) "-1.2345678901" -- 1.7.9.2