Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to test if two numbers are close in Clojure

What is the idiomatic way to test if two numbers are close to each other in Clojure?

Somewhere along the line of:

(deftest sqrt-test
   (is (~= 1.414 (Math/sqrt 2)))
like image 623
Chris Avatar asked Jul 17 '13 22:07

Chris


2 Answers

You'll need to define "close". If you ask for a "difference" of less than some tolerance, you can roll your own function using <:

(defn close? [tolerance x y]
  (< (difference x y) tolerance))

Where difference might be absolute:

(defn absolute-difference ^double [^double x ^double y]
  (Math/abs (double (- x y))))

or relative:

(defn relative-difference ^double [^double x ^double y]
  (/ (Math/abs (- x y))
     (max (Math/abs x) (Math/abs y))))

(pick your preferred definition of relative difference, of course).

Then (partial close? 0.001) will test approximate equality with tolerance of 0.001.

To discover limits on useful values of the tolerance parameter you can use Math/ulp, which is a static method which takes a double and returns the absolute difference between it and the smallest larger double.

like image 136
Michał Marczyk Avatar answered Oct 12 '22 10:10

Michał Marczyk


Although I like the solution of Michał Marczyk, note that there already is

approx=

function defined in clojure.algo.generic.math-functions. Sample usage:

clojuree.o=> (approx= 1.41 (sqrt 2) 1e-2)
true
clojuree.o=> (approx= 1.41 (sqrt 2) 1e-4)
false
like image 22
Tomas Kulich Avatar answered Oct 12 '22 08:10

Tomas Kulich