Skip to content

Instantly share code, notes, and snippets.

@mjg123
Last active December 11, 2015 21:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mjg123/4663990 to your computer and use it in GitHub Desktop.
Save mjg123/4663990 to your computer and use it in GitHub Desktop.
Lazy approach to approximating square roots in clojure using Newton-Raphson. For BrisFunctional.
line 21 sidesteps the fact that Math/abs doesn't work for clojure's Rational (ie fractional) datatype.
;; Newton-Raphson is a method for finding the square-root of a number by starting with a guess
;; then producing a next (better) guess, and iterating that process.
(defn next-guess [target guess]
(/ (+ guess (/ target guess)) 2))
;; Because iterate is produces a lazy seq, so this function does too
(defn approximations [target starting-guess]
(iterate
(partial next-guess target)
starting-guess))
;; (approximations 64 1)
;; => (1 65/2 4481/260 24405761/2330120 943126559710721/113736703642640 ...
;; an infinite list of better-and-better approximations
;; We want to consume the sequence until two successive terms are close enough together
;; preferably without "holding onto the head" of the sequence.
;; helpfully calculates the absolute difference between 2 numbers
(defn adiff [a b] (if (< a b) (- b a) (- a b)))
(defn consume-until-sated [guess-seq epsilon]
(if (> epsilon (adiff (first guess-seq) (second guess-seq)))
(* 1.0 (second guess-seq))
(recur (rest guess-seq) epsilon)))
;; this finds the first pair where the difference is less than epsilon and
;; returns the second value from that pair (as a decimal for convenience):
;;
;; (consume-until-sated (approximations 64 1) 1)
;; => 8.005147977880979
;;
;; (actually 1717394123983378202652077194241/214536212038641785250721486880, the 6th approximation)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment