Individual Project 3
Due Monday, September 23, 4:30pm
What to Hand In (see also: example project solution)
Note: pi is an intrinsic variable in Haskell. Its value is an approximation to the ratio of a circle's circumference to its diameter. The type of pi is in the Haskell class of types called Floating. Numbers in this class are represented with a finite precision. For example, Float and Double are two of the types in the class Floating. Numbers of type Float carry about seven decimal digits of precision and numbers of type Double about sixteen digits.
The argument of cosine will be a number representing an angle measured in radians. As with most measurements (as opposed to numbers produced by counting things), this number will have a fractional part. So, it will be represented in Haskell by a number in the class Fractional. You may assume a more specific type if you like - Float, for example. In this case, your type specification for cosine would be:
Compute your approximation to cosine using the first fifty terms of the Maclarin series for cosine:
This formula approximates the cosine function to many digits of accuracy throughout the range of values of interest (-10*pi to 10*pi) when all the arithmetic is done precisely. The formula will deliver an accurate result in your computations for small arguments, but will be inaccurate for large ones. Don't worry about the inaccuracy for large arguments, but if you get wrong answers for small arguments, there is something wrong with your definition.
Note: This approximation to cosine is loosely related to the methods most computing systems use to compute cosines. But, those methods are much more ingenious. First, they all alleviate (but do not eliminate) the problem with large arguments by taking advantage of the cyclic nature of the cosine function. Second, the polynomial they use as an approximation is of much lower degree. Our approximation polynomial has 50 terms; theirs computes the cosine to six digits of precision using a polynomial with only four terms (or a seven-term polynomial for sixteen-digit precision). Such compact, high-precision approximations are the remarkable products of the work of numerical analysts, one of the fields of study in the domain of computer science.
take :: Int -> [a] -> [a]
take n xs = the first n elements of the sequence xs
For example, take 3 [1, 2, 3, 4, 5, 6, 7] is [1, 2, 3]
product :: Num x => [x] -> x
product = foldr (*) 1
For example, product[1, 2, 3, 4] is 1*2*3*4.
fromIntegral :: (Integral n, Num x) => n -> x
fromIntegral n = the number of type x with the value n
The type of the value that fromIntegral delivers depends on the context the invocation appears in. For example, in the formula fromIntegral(n)/5.0, fromIntegral will deliver a value with the same type as 5.0.
The enumeration notation [n .. m] (this is Haskell notation) denotes the sequence of numbers [n, n+1, ..., m] (this is ordinary mathematical notation), and the notation [n ..] (this is Haskell notation) denotes the infinite sequence of numbers [n, n+1, n+2, ...] (this is ordinary mathematical notation) For example, [1 .. 4] means [1, 2, 3, 4] and [1 ..] denotes the infinite sequence of all integers starting from one up.
scanl :: (a -> b -> a) -> a -> [b] -> [a] scanl op z [y, x, w, v] = [z, z `op` y, (z `op` y) `op` x, ((z `op` y) `op` x) `op` w, (((z `op` y) `op` x) `op` w) `op` v]If you pursue this option, you may find the following function useful: