2

I'm following this pseudo code to convert decimal to binary recursively.

findBinary(decimal)
   if (decimal == 0)
      binary = 0
   else
      binary = decimal % 2 + 10 * (findBinary(decimal / 2)

This is what I have tried:

(defn binary [n]
  (loop [res 0]
    (if (= n 0)
    res
    (recur (res (* (+ (mod n 2) 10) (binary (quot n 2)))) )
    )
  )
)

But I get this error :

ClassCastException java.lang.Long cannot be cast to clojure.lang.IFn  user/binary (form-init9002795692676588773.clj:6)

Any ideas how to fix the code to complete the task?

1
  • When I needed to convert a decimal to binary, I used strings, so it surprised me to see the decimal converted to binary using only numbers. Neat. Commented Mar 1, 2021 at 2:08

4 Answers 4

8

I realize, that this is about the journey and not the result. But to have it mentioned: Long/toString can give you a string from a number with a wide variety of radixes.

(Long/toString 123 2)
; → "1111011"
Sign up to request clarification or add additional context in comments.

Comments

4

Here's a slightly different approach which allows recur to be used:

(defn find-binary [d]
  (loop [ decimal  d
          digits   '() ]
    (if (= decimal 0)
      (Integer. (clojure.string/join (map str digits)))
      (recur (quot decimal 2) (conj digits (mod decimal 2))))))

In the loop we build up a collection of binary digits, adding each new digit at the beginning of the list so that we end up with the digits in the desired order left-to-right in the list. When the terminating condition is reached we convert the collection-of-digits to a collection-of-strings, join the collection of strings together into single string, and convert the string back to an integer.

Comments

3

Your psuedo code can be expressed pretty directly in clojure:

(defn find-binary [decimal]
  (if (= decimal 0)
    0
    (+ (mod decimal 2) (* 10 (find-binary (quot decimal 2))))))

Examples:

user=> (find-binary 1)
1
user=> (find-binary 2)
10
user=> (find-binary 25)
11001
user=> (find-binary 255)
11111111

The error in your version is here:

  (recur (res (* (+ (mod n 2) 10) (binary (quot n 2))))

Specifically, the complaint is that you are trying to use res (which has the value 0) as a function.

To be honest, I'm not sure how to do this with loop-recur. When I try it complains about recur not being from the tail position. Perhaps another answer can enlighten us!

Comments

1

Using recur:

;; returns a binary number string of the given decimal number
(defn find-binary [decimal]
  (loop [n decimal
         res ""]
    (if (= n 0)
        res
        (recur (quot n 2)
               (str (mod n 2) res)))))

But without loop:

(defn find-binary [decimal & {:keys [acc] :or {acc ""}}]
    (if (= decimal 0)
        acc
        (find-binary (quot decimal 2) :acc (str (mod decimal 2) acc))))

The original attempt was the following, but it can't go far in the size of decimal:

(defn find-binary [decimal]
  (loop [n decimal ;; number to be binarized
         res '()   ;; collector list
         pos 0]    ;; position of binary number
    (if (= n 0)
        (reduce #'+ res) ;; sum up collector list
        (recur (quot n 2)
               (cons (* (int (Math/pow 10 pos)) 
                        (mod n 2))
                     res)
               (+ 1 pos)))))

For large numbers use:

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.