Noob Question - Clojure number rounding

4,355 views
Skip to first unread message

JDuPreez

unread,
Mar 23, 2011, 2:08:29 PM3/23/11
to Clojure
I'm trying to round a decimal number like 78.37898794 to say 78.379,
without converting it to a string. I've been struggling to get this
right and to get info on it. The closest that I've found is to use:
format "%.3f". But format converts the number to a string. Not exactly
what I'm trying to do.

How can I do this in Clojure, or where is info on how to do it? Thanks
for your help.

Meikel Brandmeyer

unread,
Mar 23, 2011, 3:07:52 PM3/23/11
to clo...@googlegroups.com
Hi,

a bit naive, but it seems to work…

user=> (defn round
[x & {p :precision}]
(if p
(let [scale (Math/pow 10 p)]
(-> x (* scale) Math/round (/ scale)))
(Math/round x)))
#'user/round
user=> (round 78.37898794)
78
user=> (round 78.37898794 :precision 3)
78.379

There are probably thousand reasons not to do that…

Sincerely
Meikel

.Bill Smith

unread,
Mar 23, 2011, 3:11:20 PM3/23/11
to clo...@googlegroups.com, Meikel Brandmeyer
Another way:

(defn myround [x precision] (-> x (bigdec) (.movePointRight precision) (+ 0.5) (int) (bigdec) (.movePointLeft precision)))

Brenton

unread,
Mar 23, 2011, 3:59:18 PM3/23/11
to Clojure
You may also consider using java interop here.

(defn round [s n]
(.setScale (bigdec n) s java.math.RoundingMode/HALF_EVEN))

=> (round 3 78.37898794)
=> 78.379

see

http://download.oracle.com/javase/1.5.0/docs/api/java/math/BigDecimal.html

Brenton

Joost

unread,
Mar 23, 2011, 5:13:34 PM3/23/11
to Clojure
Most important one being that it won't be reliable. Floats are
fundamentally not compatible with decimal rounding. You'll have to
switch to some other representation like (big) decimals, fixed point
or strings to get it.

JDuPreez

unread,
Mar 25, 2011, 5:33:15 PM3/25/11
to Clojure
Thanks so much for your answers.

OK. So from the solutions above I understand that Clojure does not
have C#'s equivalent of Math.round(7.127298, 2), and requires either
using some custom method or Java's rounding?

I think I'll rather go with the Java-interop approach.

.Bill Smith

unread,
Mar 26, 2011, 5:32:20 PM3/26/11
to clo...@googlegroups.com, JDuPreez
I think that is what Brenton posted on Mar 23.

Pascal Chatterjee

unread,
Sep 11, 2012, 9:22:35 AM9/11/12
to clo...@googlegroups.com
This doesn't seem to work for non-terminating decimals like 1/3:

(defn round [s n] 
  (.setScale (bigdec n) s java.math.RoundingMode/HALF_EVEN)) 
#'user/round
user=> (round 3 (/ 1 3))
ArithmeticException Non-terminating decimal expansion; no exact representable decimal result.  java.math.BigDecimal.divide (BigDecimal.java:1603)

 Is there a way of sending the scale to the bigdec function instead of setting it afterwards? It doesn't seem so from the docs..

// Pascal. 
Reply all
Reply to author
Forward
0 new messages