Reputation: 8193
How do I go about writing a function to convert a decimal number string to a decimal and a decimal number to a string?
Upvotes: 19
Views: 17736
Reputation: 96454
Note that read-string
gives you a floating-point number, not a decimal:
user=> (.getClass (read-string "1.01"))
java.lang.Double
The number you get back prints like what you want but it isn't, exactly.
user=> (new BigDecimal (read-string "1.01"))
1.0100000000000000088817841970012523233890533447265625M
You can use java.math.BigDecimal
instead and avoid floating-point complications:
user=> (new BigDecimal "1.01")
1.01M
user=> (.toString (new BigDecimal "1.01"))
"1.01"
Upvotes: 2
Reputation: 128111
There is very convenient clojure functions to convert from anything to string and from something resembling a number to BigDecimal:
user=> (bigdec "1234")
1234M
user=> (str 1234M)
"1234"
I guess this is clojure canonical way.
Upvotes: 42
Reputation: 40155
This example converts a numeric string into a number.
(defn String->Number [str]
(let [n (read-string str)]
(if (number? n) n nil)))
sample:
user=> (String->Number "4.5")
4.5
user=> (str 4.5)
"4.5"
user=> (String->Number "abc")
nil
Upvotes: 5
Reputation: 10695
From your question, you seem to want a toggle function, that is one that can read in a number and convert to a string and also read in a string and return a number, if the string contains numeric digits, like 123.0 or "123.0".
Here is an example:
(defn cvt-str-num [val]
(if (try
(number? val)
(catch Exception e (str "Invalid number: " (.getMessage e))))
(str val)
(let [n-val (read-string val)]
(if (number? n-val)
n-val
nil))))
I could not see a way around the let binding of n-val, because an interim place was needed to store read-string return value, so it could be tested as a number. If it is a number it is returned; else nil is returned.
Upvotes: 1