Reputation: 6509
I would like to format a 'numeric' string as a 'string number' in Clojure. This is the format mask:
"#,###,###,##0.00"
Given the string "9999.99" I would expect to receive back "9,999.99".
How would I do this in Clojure without resorting to writing a converter function i.e. using format
or something similar?
Upvotes: 1
Views: 1202
Reputation: 16194
You can use ,
in a format specifier:
(format "%,.2f" (float (clojure.edn/read-string "9999")))
=> "9,999.00"
(format "%,.2f" (Double/parseDouble "9999.126"))
=> "9,999.13"
Update to include bigdec
example:
(format "%,.2f" (bigdec "9999999999999999.12"))
=> "9,999,999,999,999,999.12"
Upvotes: 1
Reputation: 50017
It appears that in your problem domain the disadvantages and limitations of binary-base floating point (e.g. IEEE-754) are causing you some difficulty. Perhaps you should consider taking advantage of the BigDecimal support already built in to Clojure. In Clojure, the difference between a BigDecimal constant and a floating point constant is a single character; e.g. 1.2 is a Double, while 1.2M is a BigDecimal. The bigdec
function can be used to convert things to BigDecimal on the fly. For example,
(format "%,.2f" (bigdec "9999999999999999.12"))
produces
"9,999,999,999,999,999.12"
as expected. Arithmetic functions such as *
, +
, -
, and /
also work as expected.
However, this doesn't solve your basic problem. If your format string doesn't follow Java/Clojure format string conventions you'll have to write a converter function.
Best of luck.
Upvotes: 4
Reputation: 29958
You can do this using NumberFormat
. I also like the other answer (see the Java 10 Formatter
docs for details):
(ns tst.demo.core
(:use demo.core tupelo.core tupelo.test)
(:import [java.text NumberFormat]
[java.util Locale]))
(dotest
(let [value (Double/valueOf "1234567.89")
nf (NumberFormat/getNumberInstance (Locale/US))
s1a (.format nf (.doubleValue value))
s1b (format "%,05.2f" value)]
(spyx s1a)
(spyx s1b))
s1a => "1,234,567.89"
s1b => "1,234,567.89"
(let [value (Double/valueOf "1.2")
nf (NumberFormat/getNumberInstance (Locale/US))
s1a (.format nf (.doubleValue value))
s1b (format "%,05.2f" value)]
(spyx s1a)
(spyx s1b)))
s1a => "1.2"
s1b => "01.20"
Here is how to do it for BigDecimal, using first Java interop and then a built-in Clojure function bigdec
:
(format "%,05.2f" (BigDecimal. "9999999999999999.12")) => "9,999,999,999,999,999.12"
(format "%,05.2f" (bigdec "9999999999999999.12")) => "9,999,999,999,999,999.12"
Upvotes: 1