Solving quadratic equation in Clojure I wrote a function in Clojure to solve quadratic equations using the quadratic formula

The function

(defn solvequadeq [a b c]
 (let [D (- (* b b) (* 4 a c))]
      (if (&lt; D 0) #{}
        (let [sqrtD (Math/sqrt D)
              x1 (/ (+ (- b) sqrtD) (* 2 a))
              x2 (/ (- (- b) sqrtD) (* 2 a))]
              (set [x1 x2])))))


Unit tests

(defn assertFuzzyEquals [act exp]    ;; From codewars.com
  (do (println "asserting equality over " act exp)
  (let [inrange (&lt;= (Math/abs (- act exp)) 1e-2)]
    (if (= inrange false)
      (println "abs(actual - expected) must be &lt;= 1e-2. Expected was " exp " but got: " act))
    (is (= inrange true))))
)

(defn assertSetsFuzzyEqual [act exp]
  (and (is (= (count act) (count exp)))
  (doall (map assertFuzzyEquals (sort (vec act)) (sort (vec exp))))))   ; (1)


(deftest a-test5
  (testing "Solve quadratic equations"
          (assertSetsFuzzyEqual (solvequadeq 1 0 0) #{0})
          (assertSetsFuzzyEqual (solvequadeq 1 -6 9) #{3})
          (assertSetsFuzzyEqual (solvequadeq 1 -4 3) #{1 3})
          (assertSetsFuzzyEqual (solvequadeq 1 -4 14) #{})
))


N.B.: assertFuzzyEquals is borrowed from a task of codewars.com, all the rest is my code.

While any remark, and suggestion is welcome, I would be interested most particularly in the following questions:


Is using a set a good solution for avoiding having the same return value twice, if the two solutions are equal? (I am worrying that they might not be always exactly equal, due to imprecision in calculation.)
If not, than what would be a better approach, to elegantly handle the case of one vs two solutions?
Independently whether sets should be used for this particular problem or not, is there a better way to compare two sets for equality, with a custom function between the elements? (C.f., line (1))


EDIT: Clarification of this last point, as per the answer of Josh.
The question is: what is the best practice, in Clojure, for checking the equality of two sets of floating point numbers?

Let's say, that we have a set with values #{1.0, 2.0}, and want to compare it against the set #{1, 2}.

Attempted solutions:

(= #{1.0, 2.0} #{1, 2})

; result false, since 1.0 != 1

(reduce #(and %1 %2)  (map #(&gt; 0.01 (Math/abs (- %1 %2))) #{1.0,2.0}  #{2,1}))

; returns false, since ordering of elements in the set is not guaranteed

(reduce #(and %1 %2)  (map #(&gt; 0.01 (Math/abs (- %1 %2))) (sort (vec #{1.0,2.0}))  (sort (vec #{2,1}))))

; returns true, because fixes the ordering, but is very complicated...

So, I am asking if there is a better way, to compare two sets, providing a custom function for equality checking (in this particular case, this custom function would be #(&gt; 0.01 (Math/abs (- %1 %2)))).

I am thinking of something like this (pseudo-code only):
(sets-equal #(&gt; 0.01 (Math/abs (- %1 %2))) #{1.0,2.0}  #{2,1}
Is using a set a good solution for avoiding having the same return value twice, if the two solutions are equal? (I am worrying that they might not be always exactly equal, due to imprecision in calculation.)


Instead of a set, IMO a vector would be a better structure.  It is essentially a "list of solutions."  Instead of your (set [x1 x2... simply wrap it in a vector:

(vec (hash-set x1 x2))


There's nothing wrong with using a set, but vectors are more common. Sets tend to be used more for utility in computation, rather than as a way to convey expression results.  There are always exceptions, and you could very well make one here if you chose to do so.


  Independently whether sets should be used for this particular problem or not, is there a better way to compare two sets for equality, with a custom function between the elements? (C.f., line (1))


I'm not the expert on floating-point comparisons, but I wonder if the following would work, or if it's too naive:

(def s1 #{1.0 2.0})
(def s2 #{1 2})
(= (set (map double s1)) (set (map double s2)))  ; true