0

I need to create a continued fraction function to find the square root of a number and use it in a square root function. the series I am using and the rearranged version for code is shown above.

(define (contfrac x)
   (cond
     ((= x 0) 1)
     (contfrac (/ (- x 1) (+ 2 (- x 1))))))

This is my continued fraction function, it seems to be working to check the initial fraction but I am having trouble having it continue past the second fraction and implementing it in the (newsquareroot x y) functions x variable to determine x's square root and y is the number of times the continued fraction is recursively called. I am not sure if I should change the contfract function to call itself a certain amount of times or do it within the newsquareroot function. continued fraction series

coredump
  • 37,664
  • 5
  • 43
  • 77

1 Answers1

1

Probably the best way to do this is through matrix multiplication as square roots of positive numbers are trivially represented. If a is the integer square root of N and b = N-a^2 then the continued fraction is a+b/(2a+b/(2a+b ...)). This can be represented by the infinite matrix product ((a b)(1 0)) times the infinite product ((2a b)(1 0)) to as much precision as you like. When you have as many terms as you want, just take the rational as the first column.

Here's an example that should be easy to extend.

#lang racket/base
(require math/number-theory)

(define (times left right)
  (define (transpose m)
    (apply map list m))
  (define r (transpose right))
  (for/list ((row left))
    (for/list ((col r))
      (apply + (map * row col)))))

(define iterations (make-parameter 50))

(define (square-root N)
  (define a (integer-root N 2))
  (define b (- N (* a a)))
  (if (zero? b)
      a
      (let* ((first-matrix (list (list a b) (list 1 0)))
             (2a (* 2 a))
             (rest-matrix (list (list 2a b) (list 1 0))))
        (let ((result-matrix
               (for/fold ((accum first-matrix))
                         ((i (in-range (iterations))))
                 (times accum rest-matrix))))
          (apply / (map car result-matrix))))))
 ;;;;;;
Welcome to DrRacket, version 6.12 [3m].
Language: racket/base [custom]; memory limit: 16384 MB.
> (square-root 2)
1 4866752642924153522/11749380235262596085
> (- (sqrt 2) (square-root 2))
0.0
> (square-root 23)
;;;4 and a huge fraction that breaks formatting here
> (- (sqrt 23) (square-root 23))
0.0
> 

There is by the way a continued fraction package available but it is a little more complicated than this and built on sequences.

EDIT Since this was tagged r5rs I should have written it that way. I am not 100% sure on racket/r5rs compliance but this runs.

#lang r5rs

(define (transpose m)
  (apply map list m))

(define (row*col r c)
  (apply + (map * r c)))

(define (make-row* r)
  (lambda(c) (row*col r c)))

(define (times left right)
  (let ((r (transpose right)))
    (let loop ((rows left))
      (if (null? rows)
          '()
          (cons (map (make-row* (car rows))
                     r)
                (loop (cdr rows)))))))

(define (matrix-expt m e)
  (cond ((= 1 e) m)
        ((even? e) (matrix-expt (times m m)
                                (/ e 2)))
        (else (times m (matrix-expt (times m m)
                                    (/ (- e 1) 2))))))

(define (integer-root N exp)
  (letrec ((recur (lambda(i)
                    (let ((next (+ 1 i)))
                      (if (< N (expt next exp))
                          i
                          (recur next))))))
    (recur 1)))

(define (square-root N iters)
  (let* ((a (integer-root N 2))
         (b (- N (* a a))))
    (if (zero? b)
        a
        (let* ((first-matrix (list (list a b)
                                   (list 1 0)))
               (2a (* 2 a))
               (rest-matrix (list (list 2a b)
                                  (list 1 0)))
               (result-matrix
                (times first-matrix
                       (matrix-expt rest-matrix
                                    iters))))
          (apply / (map car result-matrix))))))
law-of-fives
  • 643
  • 4
  • 8
  • Any idea how to express this in terms of the R5RS language? –  Feb 07 '18 at 13:39
  • Yes. You'd need to write your own `integer-root` procedure, convert the inner definitions in terms of let/letrec/etc., replace the parameter with whatever suits you, and convert the for/* forms to recursion. Do you need me to edit the example or are you going to try on your own? – law-of-fives Feb 07 '18 at 14:08
  • I am attempting it on my own, but if you have a chance to edit that would be great. New to the language and using the let function so it would be very helpful. –  Feb 07 '18 at 14:51
  • @ajs well this should give you plenty to chew on – law-of-fives Feb 07 '18 at 15:51