2015-02-14 12:33 GMT+01:00 Cecil Westerhof <[email protected]>:
>
> 2015-02-11 8:32 GMT+01:00 Cecil Westerhof <[email protected]>:
>
>>
>> I needed a function to get the percentage as an int. Input is place and
>> total-count.
>> I want the normal definition (which is the default) and a high and low
>> variant.
>>
>> I came up with the following code:
>> (defn get-percentage
>> ([place total-count] (get-percentage :normal place total-count))
>> ([mode place total-count]
>> (let [percentage
>>
>> (/ (* place 100.0) total-count)]
>> (condp = mode
>> :high (int (Math/ceil percentage))
>> :low (int (Math/floor percentage))
>> :normal (int (Math/round percentage))
>> (throw (Exception. "ERROR: get-percentage
>> [:high|:low|:normal] <PLACE> <TOTAL_COUNT>"))))))
>>
>> Is this a good version, or could it be done better?
>>
>
> Everyone thanks for the comments. I did the following.
>
> I made three round functions:
> (defn round [x] (int (Math/round x)))
> (defn round-high [x] (int (Math/ceil x)))
> (defn round-low [x] (int (Math/floor x)))
>
> And rewrote get-percentage to:
> (defn get-percentage
> ([place total-count] (get-percentage :normal place total-count))
> ([mode place total-count]
>
> (let [mode-fn (case mode
> :high round-high
> :low round-low
> :normal round
> (throw (Exception.
> "ERROR: get-percentage [:high|:low|:normal]
> <PLACE> <TOTAL_COUNT>")))]
> (-> place (* 100.0) (/ total-count) mode-fn int))))
>
> But I wanted to do it a little neater.
>
> I wrote a new round function:
> (defn round
> ([x] (round :normal x))
> ([mode x]
> (println mode)
> (println x)
> (case mode
> :high (Math/ceil x)
> :low (Math/floor x)
> :normal (Math/round x)
> (throw (Exception.
> "ERROR: round [:high|:low|:normal] <VALUE>")))))
>
> Then I tried to rewrite get-percentage:
> (defn get-percentage
> ([place total-count] (get-percentage :normal place total-count))
> ([mode place total-count]
>
> (if-not (contains? #{:high :low :normal} mode)
> (throw (Exception.
> "ERROR: get-percentage [:high|:low|:normal]
> <PLACE> <TOTAL_COUNT>")))
> (round mode (/ (* place 100.0) total-count))))
>
> But this gives on the last line:
> CompilerException java.lang.RuntimeException: Unable to resolve
> symbol: in this context,
>
> When I put before that statement:
> (println mode)
> (println place)
> (println total-count)
> (println (/ place total-count))
> (println (/ (* place 100.0) total-count))
>
> I get the same error on:
> (println (/ place total-count))
>
> What is happening here?
>
> I am using Clojure 1.6.0 on Linux.
>
I have now something that is working OK I think. This is what it has
become:
(defmacro static-fn [f] `(fn [x#] (~f x#)))
(defn round
([x] (round :normal x))
([mode x]
(let [fn (case mode
:high (static-fn Math/ceil)
:low (static-fn Math/floor)
:normal (static-fn Math/round)
(throw (Exception.
"ERROR: round [:high|:low|:normal] <VALUE>")))]
(long (fn x)))))
(defn get-percentage
([place total-count] (get-percentage :normal place total-count))
([mode place total-count]
(if-not (contains? #{:high :low :normal} mode)
(throw (Exception.
"ERROR: get-percentage [:high|:low|:normal] <PLACE>
<TOTAL_COUNT>")))
(round mode (/ (* place 100.0) total-count))))
I made two other handy functions:
(defn round-precision [value precision]
(let [multiplier (Math/pow 10.0 precision)]
(/ (Math/round (* value multiplier)) multiplier)))
(defn round-div-precision [dividend divisor precision]
(round-precision (/ (float dividend) divisor) precision))
For example:
(round-div-precision 22000 7 3)
gives:
3142.857
and:
(round-div-precision 22000 7 -3)
gives:
3000.0
--
Cecil Westerhof
--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to [email protected]
Note that posts from new members are moderated - please be patient with your
first post.
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
---
You received this message because you are subscribed to the Google Groups
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.