How would I create an approximate cos function.
What I have so far.
(define k 0)
(define (approx-cos x n)
(cond
[(> 0 n) 0]
[else (* (/ (expt -1 k) (factorial (* 2 k))) (expt x (* 2 k)))]))
Your solution requires a lot of work before it meets the expectations. For starters, your parameters are switched: the first one is the number you want to calculate and the second one is the number of iterations...
Which leads me to the major problem in your solution, you're not iterating at all! You're supposed to call approx-cos at some point, or some helper procedure to do the looping (as I did).
Last but not least, you're not correctly implementing the formula. Where's the -1 part, for instance? Or where are you multiplying by x^2k? I'm afraid a complete rewrite is in order:
; main procedure
(define (approx-cos x n)
; call helper procedure
(loop 0 0 x n))
; define a helper procedure
(define (loop acc k x n)
; loop with k from 0 to n, accumulating result
(cond [(> k n) acc] ; return accumulator
[else
(loop (+ acc ; update accumulator
(* (/ (expt -1.0 k) ; implement the formula
(factorial (* 2.0 k)))
(expt x (* 2.0 k))))
(add1 k) ; increment iteration variable
x n)]))
This will pass all the check expects:
(approx-cos 0 0)
=> 1
(approx-cos (/ pi 2) 0)
=> 1
(approx-cos 0 10)
=> 1
(approx-cos pi 10)
=> -0.9999999999243502
(approx-cos (* 3 (/ pi 2)) 9)
=> -1.1432910825361444e-05
(approx-cos 10 100)
=> -0.8390715290756897
Some final thoughts: your implementation of factorial is very slow, if you plan to do a larger number of iterations, your factorial will freeze the execution at some point.
Related
This is the code to calculate the failure function (how many steps we have to go back) in Scheme, when we use the Knuth-Morris-Pratt algorithm:
(define (compute-failure-function p)
(define n-p (string-length p))
(define sigma-table (make-vector n-p 0))
(let loop
((i-p 2)
(k 0))
(cond
((>= i-p n-p)
(vector-set! sigma-table (- n-p 1) k))
((eq? (string-ref p k)
(string-ref p (- i-p 1)))
(vector-set! sigma-table i-p (+ k 1))
(loop (+ i-p 1) (+ k 1)))
((> k 0)
(loop i-p (vector-ref sigma-table k)))
(else ; k=0
(vector-set! sigma-table i-p 0)
(loop (+ i-p 1) k))))
(vector-set! sigma-table 0 -1)
(lambda (q)
(vector-ref sigma-table q)))
But I do not understand the part when k > 0. Can someone explain it please?
I see you're confused with the syntax of a named let. This post does a good job explaining how it works, but perhaps an example with more familiar syntax will make things clearer. Take this code in Python, it adds all integers from 1 to 10:
sum = 0
n = 1
while n <= 10:
sum += n
n += 1
print(sum)
=> 55
Now let's try to write it in a recursive fashion, I'll call my function loop. This is completely equivalent:
def loop(n, sum):
if n > 10:
return sum
else:
return loop(n + 1, n + sum)
loop(1, 0)
=> 55
In the above example, the loop function implements an iteration, the parameter n is used to keep track of the current position, and the parameter sum accumulates the answer. Now let's write the exact same code, but in Scheme:
(let loop ((n 1) (sum 0))
(cond ((> n 10) sum)
(else (loop (+ n 1) (+ n sum)))))
=> 55
Now we've defined a local procedure called loop which is then automatically called with the initial values 1 and 0 for its parameters n and sum. When the base case of the recursion is reached, we return sum, otherwise we keep calling this procedure, passing updated values for the parameters. It's exactly the same as in the Python code! Don't be confused by the syntax.
In your algorithm, i-p and k are the iteration variables, which are initialized to 2 and 0 respectively. Depending on which condition is true, the iteration continues when we call loop again with updated values for i-p and k, or it ends when the case (>= i-p n-p) is reached, at this point the loop exits and the computed value is in the variable sigma-table. The procedure ends by returning a new function, referred to as the "failure function".
I've spent some time looking at the questions about this on here and throughout the internet but I can't really find anything that makes sense to me.
Basically I need help on realizing a function in scheme that evaluates Leibniz's formula when you give it a value k. The value you input lets the function know how many values in the series it should compute. This is what I have so far, I'm not sure what way I need to write this program to make it work. Thanks!
(define (fin-alt-series k)
(cond ((= k 1)4)
((> k 1)(+ (/ (expt -1 k) (+(* 2.0 k) 1.0)) (fin-alt-series (- k 1.0))))))
The base case is incorrect. And we can clean-up the code a bit:
(define (fin-alt-series k)
(cond ((= k 0) 1)
(else
(+ (/ (expt -1.0 k)
(+ (* 2 k) 1))
(fin-alt-series (- k 1))))))
Even better, we can rewrite the procedure to use tail recursion, it'll be faster this way:
(define (fin-alt-series k)
(let loop ((k k) (sum 0))
(if (< k 0)
sum
(loop (- k 1)
(+ sum (/ (expt -1.0 k) (+ (* 2 k) 1)))))))
For example:
(fin-alt-series 1000000)
=> 0.7853984133971936
(/ pi 4)
=> 0.7853981633974483
I need to write a function that will return the number of ways in which can be n (n is a natural number) written as the sum of natural numbers.
For example: 4 can be written as 1+1+1+1, 1+1+2, 2+2, 3+1 and 4.
I have written a function that returns the number of all the options, but does not take into account that the possibilities 1 + 1 + 2 and 2 + 1 + 1 (and all similar cases) are equal. So for n=4 it returns 8 instead of 5.
Here is my function:
(define (possibilities n)
(define (loop i)
(cond [(= i n) 1]
[(> i n) 0]
[(+ (possibilities (- n i)) (loop (+ i 1)))]))
(cond [(< n 1) 0]
[#t (loop 1)]))
Could you please help me with fixing my function, so it will work the way it should be. Thank you.
This is a well-known function, it's called the partition function P, its possible values are referenced as A000041 in the on-line encyclopedia of integer sequences.
One simple solution (not the fastest!) would be to use this helper function, which denotes the number of ways of writing n as a sum of exactly k terms:
(define (p n k)
(cond ((> k n) 0)
((= k 0) 0)
((= k n) 1)
(else
(+ (p (sub1 n) (sub1 k))
(p (- n k) k)))))
Then we just have to add the possible results, being careful with the edge cases:
(define (possibilities n)
(cond ((negative? n) 0)
((zero? n) 1)
(else
(for/sum ([i (in-range (add1 n))])
(p n i)))))
For example:
(map possibilities (range 11))
=> '(1 1 2 3 5 7 11 15 22 30 42)
Im making a scheme program that calculates
cos(x) = 1-(x^2/2!)+(x^4/4!)-(x^6/6!).......
whats the most efficient way to finish the program and how would you do the alternating addition and subtraction, thats what I used the modulo for but doesnt work for 0 and 1 (first 2 terms). x is the intial value of x and num is the number of terms
(define cosine-taylor
(lambda (x num)
(do ((i 0 (+ i 1)))
((= i num))
(if(= 0 (modulo i 2))
(+ x (/ (pow-tr2 x (* i 2)) (factorial (* 2 i))))
(- x (/ (pow-tr2 x (* i 2)) (factorial (* 2 i))))
))
x))
Your questions:
whats the most efficient way to finish the program? Assuming you want use the Taylor series expansion and simply sum up the terms n times, then your iterative approach is fine. I've refined it below; but your algorithm is fine. Others have pointed out possible loss of precision issues; see below for my approach.
how would you do the alternating addition and subtraction? Use another 'argument/local-variable' of odd?, a boolean, and have it alternate by using not. When odd? subtract when not odd? add.
(define (cosine-taylor x n)
(let computing ((result 1) (i 1) (odd? #t))
(if (> i n)
result
(computing ((if odd? - +) result (/ (expt x (* 2 i)) (factorial (* 2 i))))
(+ i 1)
(not odd?)))))
> (cos 1)
0.5403023058681398
> (cosine-taylor 1.0 100)
0.5403023058681397
Not bad?
The above is the Scheme-ish way of performing a 'do' loop. You should easily be able to see the correspondence to a do with three locals for i, result and odd?.
Regarding loss of numeric precision - if you really want to solve the precision problem, then convert x to an 'exact' number and do all computation using exact numbers. By doing that, you get a natural, Scheme-ly algorithm with 'perfect' precision.
> (cosine-taylor (exact 1.0) 100)
3982370694189213112257449588574354368421083585745317294214591570720658797345712348245607951726273112140707569917666955767676493702079041143086577901788489963764057368985531760218072253884896510810027045608931163026924711871107650567429563045077012372870953594171353825520131544591426035218450395194640007965562952702049286379961461862576998942257714483441812954797016455243/7370634274437294425723020690955000582197532501749282834530304049012705139844891055329946579551258167328758991952519989067828437291987262664130155373390933935639839787577227263900906438728247155340669759254710591512748889975965372460537609742126858908788049134631584753833888148637105832358427110829870831048811117978541096960000000000000000000000000000000000000000000000000
> (inexact (cosine-taylor (exact 1.0) 100))
0.5403023058681398
we should calculate the terms in iterative fashion to prevent the loss of precision from dividing very large numbers:
(define (cosine-taylor-term x)
(let ((t 1.0) (k 0))
(lambda (msg)
(case msg
((peek) t)
((pull)
(let ((p t))
(set! k (+ k 2))
(set! t (* (- t) (/ x (- k 1)) (/ x k)))
p))))))
Then it should be easy to build a function to produce an n-th term, or to sum the terms up until a term is smaller than a pre-set precision value:
(define t (cosine-taylor-term (atan 1)))
;Value: t
(reduce + 0 (map (lambda(x)(t 'pull)) '(1 2 3 4 5)))
;Value: .7071068056832942
(cos (atan 1))
;Value: .7071067811865476
(t 'peek)
;Value: -2.4611369504941985e-8
A few suggestions:
reduce your input modulo 2pi - most polynomial expansions converge very slowly with large numbers
Keep track of your factorials rather than computing them from scratch each time (once you have 4!, you get 5! by multiplying by 5, etc)
Similarly, all your powers are powers of x^2. Compute x^2 just once, then multiply the "x power so far" by this number (x2), rather than taking x to the n'th power
Here is some python code that implements this - it converges with very few terms (and you can control the precision with the while(abs(delta)>precision): statement)
from math import *
def myCos(x):
precision = 1e-5 # pick whatever you need
xr = (x+pi/2) % (2*pi)
if xr > pi:
sign = -1
else:
sign = 1
xr = (xr % pi) - pi/2
x2 = xr * xr
xp = 1
f = 1
c = 0
ans = 1
temp = 0
delta = 1
while(abs(delta) > precision):
c += 1
f *= c
c += 1
f *= c
xp *= x2
temp = xp / f
c += 1
f *= c
c += 1
f *= c
xp *= x2
delta = xp/f - temp
ans += delta
return sign * ans
Other than that I can't help you much as I am not familiar with scheme...
For your general enjoyment, here is a stream implementation. The stream returns an infinite sequence of taylor terms based on the provided func. The func is called with the current index.
(define (stream-taylor func)
(stream-map func (stream-from 0)))
(define (stream-cosine x)
(stream-taylor (lambda (n)
(if (zero? n)
1
(let ((odd? (= 1 (modulo n 2))))
;; Use `exact` if desired...
;; and see #WillNess above; save 'last'; use for next; avoid expt/factorial
((if odd? - +) (/ (expt x (* 2 n)) (factorial (* 2 n)))))))))
> (stream-fold + 0 (stream-take 10 (stream-cosine 1.0)))
0.5403023058681397
Here's the most streamlined function I could come up with.
It takes advantage of the fact that the every term is multiplied by (-x^2) and divided by (i+1)*(i+2) to come up with the text term.
It also takes advantage of the fact that we are computing factorials of 2, 4, 6. etc. So it increments the position counter by 2 and compares it with 2*N to stop iteration.
(define (cosine-taylor x num)
(let ((mult (* x x -1))
(twice-num (* 2 num)))
(define (helper iter prev-term prev-out)
(if (= iter twice-num)
(+ prev-term prev-out)
(helper (+ iter 2)
(/ (* prev-term mult) (+ iter 1) (+ iter 2))
(+ prev-term prev-out))))
(helper 0 1 0)))
Tested at repl.it.
Here are some answers:
(cosine-taylor 1.0 2)
=> 0.5416666666666666
(cosine-taylor 1.0 4)
=> 0.5403025793650793
(cosine-taylor 1.0 6)
=> 0.5403023058795627
(cosine-taylor 1.0 8)
=> 0.5403023058681398
(cosine-taylor 1.0 10)
=> 0.5403023058681397
(cosine-taylor 1.0 20)
=> 0.5403023058681397
The following is code that I wrote for newtons method:
(define (newtons-method f guess n)
(define (newtons-method-h guess k)
(if(= k n)
guess
(let ((next (- guess (/ (f guess) ((der f 0.1) guess)))))
(newtons-method-h next (+ k 1)))))
(newtons-method-h guess 0))
As well as code that I wrote to find square roots of numbers using newton's method:
(define (sqrt-newt n)
(newtons-method (lambda (x) (- (* x x) n)) 1.0 40))
I am wondering... Does sqrt-newt call newtons-method for 40 interations? I believe the answer is yes, but I am drawing a blank here.
Just add a counter to you code:
(define counter null) ; define a global variable
(define (newtons-method f guess n)
(define (newtons-method-h guess k)
(set! counter (add1 counter)) ; increment it at each call
(if (= k n)
guess
(let ((next (- guess (/ (f guess) ((der f 0.1) guess)))))
(newtons-method-h next (+ k 1)))))
(set! counter 0) ; initialize it before starting
(newtons-method-h guess 0))
(sqrt-newt 2) ; run the procedure
=> 1.4142135623730951
counter ; check the counter's value
=> 41
As you can see, the newtons-method-h procedure got called 41 times - one more than you expected, because the procedure gets invoked one last time when (= k n) and that's when the recursion ends.